rewrote projector overlay widget
This commit is contained in:
parent
2dc0cc83f1
commit
198eefbfdd
Binary file not shown.
@ -2105,7 +2105,7 @@ msgstr "Einblendungen"
|
||||
|
||||
#: projector/templates/projector/control.html:193
|
||||
msgid "sec"
|
||||
msgstr "s"
|
||||
msgstr "sek"
|
||||
|
||||
#: projector/templates/projector/control.html:194
|
||||
msgid "Save as default"
|
||||
|
1076
openslides/projector/static/javascript/jquery.form.js
Normal file
1076
openslides/projector/static/javascript/jquery.form.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,85 @@
|
||||
* :license: GNU GPL, see LICENSE for more details.
|
||||
*/
|
||||
|
||||
// function that writes the portlet list order to a cookie
|
||||
function saveOrder() {
|
||||
$(".column").each(function(index, value){
|
||||
var colid = value.id;
|
||||
var cookieName = "cookie-" + colid;
|
||||
// Get the order for this column.
|
||||
var order = $('#' + colid).sortable("toArray");
|
||||
// For each portlet in the column
|
||||
for ( var i = 0, n = order.length; i < n; i++ ) {
|
||||
// Determine if it is 'opened' or 'closed'
|
||||
var v = $('#' + order[i] ).find('.portlet-content').is(':visible');
|
||||
// Modify the array we're saving to indicate what's open and
|
||||
// what's not.
|
||||
order[i] = order[i] + ":" + v;
|
||||
}
|
||||
$.cookie(cookieName, order, { path: "/", expiry: new Date(2012, 1, 1)});
|
||||
});
|
||||
}
|
||||
|
||||
// function that restores the portlet list order from a cookie
|
||||
function restoreOrder() {
|
||||
$(".column").each(function(index, value) {
|
||||
var colid = value.id;
|
||||
var cookieName = "cookie-" + colid
|
||||
var cookie = $.cookie(cookieName);
|
||||
if ( cookie == null ) { return; }
|
||||
var IDs = cookie.split(",");
|
||||
for (var i = 0, n = IDs.length; i < n; i++ ) {
|
||||
var toks = IDs[i].split(":");
|
||||
if ( toks.length != 2 ) {
|
||||
continue;
|
||||
}
|
||||
var portletID = toks[0];
|
||||
var visible = toks[1]
|
||||
var portlet = $(".column")
|
||||
.find('#' + portletID)
|
||||
.appendTo($('#' + colid));
|
||||
if (visible === 'false') {
|
||||
portlet.find(".ui-icon").toggleClass("ui-icon-minus");
|
||||
portlet.find(".ui-icon").toggleClass("ui-icon-plus");
|
||||
portlet.find(".portlet-content").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$( ".column" ).sortable({
|
||||
connectWith: ".column",
|
||||
stop: function() { saveOrder(); }
|
||||
});
|
||||
|
||||
$(".portlet")
|
||||
.addClass("ui-widget ui-widget-content")
|
||||
.addClass("ui-helper-clearfix ui-corner-all")
|
||||
.find(".portlet-header")
|
||||
.addClass("ui-widget-header ui-corner-all")
|
||||
.prepend('<span class="ui-icon ui-icon-minus"></span>')
|
||||
.end()
|
||||
.find(".portlet-content");
|
||||
|
||||
restoreOrder();
|
||||
|
||||
$(".portlet-header .ui-icon").click(function() {
|
||||
$(this).toggleClass("ui-icon-minus");
|
||||
$(this).toggleClass("ui-icon-plus");
|
||||
$(this).parents(".portlet:first").find(".portlet-content").toggle();
|
||||
saveOrder(); // This is important
|
||||
});
|
||||
|
||||
if ($.browser.msie) {
|
||||
if ($.browser.version >= 8.0 && $.browser.version < 9.0)
|
||||
{
|
||||
/* scaling bug in IE8.. iframe has to be 4 times bigger */
|
||||
$( "#iframe" ).css('width', 1024 * 4);
|
||||
$( "#iframe" ).css('height', 768 * 4);
|
||||
}
|
||||
$( "#iframe" ).css('zoom', '0.25');
|
||||
}
|
||||
// activate an element to show it on projector
|
||||
$('.activate_link').click(function(event) {
|
||||
event.preventDefault();
|
||||
@ -14,7 +92,6 @@ $(function() {
|
||||
type: 'GET',
|
||||
url: $(this).attr('href'),
|
||||
dataType: 'json',
|
||||
data: '',
|
||||
success: function(data) {
|
||||
$('.activate_link').removeClass('active');
|
||||
$('li').removeClass('activeline');
|
||||
@ -28,6 +105,25 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$('a.overlay').click(function(event) {
|
||||
event.preventDefault();
|
||||
var link = $(this);
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $(this).attr('href'),
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if (data['active']) {
|
||||
$('#' + data['def_name'] + '_active').show();
|
||||
$('#' + data['def_name'] + '_inactive').hide();
|
||||
} else {
|
||||
$('#' + data['def_name'] + '_active').hide();
|
||||
$('#' + data['def_name'] + '_inactive').show();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// control the projector
|
||||
$('.projector_edit').click(function(event) {
|
||||
event.preventDefault();
|
||||
@ -42,7 +138,7 @@ $(function() {
|
||||
});
|
||||
|
||||
// control countdown
|
||||
$('.projector_countdown_btn').click(function(event) {
|
||||
$('.countdown_control').click(function(event) {
|
||||
event.preventDefault();
|
||||
var link = $(this);
|
||||
var requestData = {};
|
||||
@ -56,6 +152,14 @@ $(function() {
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if (data['state'] == 'active') {
|
||||
$('#countdown_play').hide();
|
||||
$('#countdown_stop').show();
|
||||
} else {
|
||||
$('#countdown_play').show();
|
||||
$('#countdown_stop').hide();
|
||||
}
|
||||
$('#countdown_time').val(data['countdown_time'])
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -78,4 +182,8 @@ $(function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#overlay-form').ajaxForm(function() {
|
||||
alert("Thank you for your comment!");
|
||||
});
|
||||
});
|
||||
|
@ -39,49 +39,12 @@
|
||||
}
|
||||
|
||||
/*.projector_countdown_spinval {*/
|
||||
|
||||
#countdown_time {
|
||||
width: 40px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.projector_countdown_spinbox {
|
||||
height: 16px;
|
||||
width: auto;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.projector_countdown_spinup {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 35px;
|
||||
}
|
||||
|
||||
.projector_countdown_spindown {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 35px;
|
||||
}
|
||||
|
||||
.projector_countdown_btn img {
|
||||
padding-top: 8px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* countdown control buttons */
|
||||
.play{
|
||||
background:url(../images/icons/play.png) no-repeat 0px 0px;
|
||||
text-indent: 14px !important;
|
||||
}
|
||||
.pause{
|
||||
background:url(../images/icons/pause.png) no-repeat 0px 0px;
|
||||
text-indent: 14px !important;
|
||||
}
|
||||
.backward{
|
||||
background:url(../images/icons/skip-backward.png) no-repeat 0px 0px;
|
||||
text-indent: 14px !important;
|
||||
}
|
||||
|
||||
/* iframe */
|
||||
#iframe {
|
||||
-moz-transform-origin: 0 0;
|
||||
@ -127,3 +90,22 @@ a.activate_link div {
|
||||
a.activate_link.active div {
|
||||
background-image: url(../images/icons/accept.png);
|
||||
}
|
||||
|
||||
a.overlay div {
|
||||
background-image: url(../images/icons/accept-grey.png);
|
||||
background-repeat: no-repeat;
|
||||
float: left;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding-right: 16px;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
}
|
||||
|
||||
a.overlay.active div {
|
||||
background-image: url(../images/icons/accept.png);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -10,119 +10,7 @@
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery-ui-1.8.18.custom.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/projector-control.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery.cookie.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function switchButtons(which) {
|
||||
if (which == 'stop') {
|
||||
$( "#countdown_play" ).hide();
|
||||
$( "#countdown_stop" ).show();
|
||||
}
|
||||
else {
|
||||
$( "#countdown_play" ).show();
|
||||
$( "#countdown_stop" ).hide();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
function spinCount(delta) {
|
||||
var count = parseInt($( "#countdown_time" ).val());
|
||||
if (count + delta < 0) {
|
||||
delta = 0;
|
||||
}
|
||||
$( "#countdown_time" ).val(count + delta);
|
||||
return false;
|
||||
};
|
||||
|
||||
// function that writes the portlet list order to a cookie
|
||||
function saveOrder() {
|
||||
$(".column").each(function(index, value){
|
||||
var colid = value.id;
|
||||
var cookieName = "cookie-" + colid;
|
||||
// Get the order for this column.
|
||||
var order = $('#' + colid).sortable("toArray");
|
||||
// For each portlet in the column
|
||||
for ( var i = 0, n = order.length; i < n; i++ ) {
|
||||
// Determine if it is 'opened' or 'closed'
|
||||
var v = $('#' + order[i] ).find('.portlet-content').is(':visible');
|
||||
// Modify the array we're saving to indicate what's open and
|
||||
// what's not.
|
||||
order[i] = order[i] + ":" + v;
|
||||
}
|
||||
$.cookie(cookieName, order, { path: "/", expiry: new Date(2012, 1, 1)});
|
||||
});
|
||||
}
|
||||
|
||||
// function that restores the portlet list order from a cookie
|
||||
function restoreOrder() {
|
||||
$(".column").each(function(index, value) {
|
||||
var colid = value.id;
|
||||
var cookieName = "cookie-" + colid
|
||||
var cookie = $.cookie(cookieName);
|
||||
if ( cookie == null ) { return; }
|
||||
var IDs = cookie.split(",");
|
||||
for (var i = 0, n = IDs.length; i < n; i++ ) {
|
||||
var toks = IDs[i].split(":");
|
||||
if ( toks.length != 2 ) {
|
||||
continue;
|
||||
}
|
||||
var portletID = toks[0];
|
||||
var visible = toks[1]
|
||||
var portlet = $(".column")
|
||||
.find('#' + portletID)
|
||||
.appendTo($('#' + colid));
|
||||
if (visible === 'false') {
|
||||
portlet.find(".ui-icon").toggleClass("ui-icon-minus");
|
||||
portlet.find(".ui-icon").toggleClass("ui-icon-plus");
|
||||
portlet.find(".portlet-content").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$(function() {
|
||||
$( ".column" ).sortable({
|
||||
connectWith: ".column",
|
||||
stop: function() { saveOrder(); }
|
||||
});
|
||||
|
||||
$(".portlet")
|
||||
.addClass("ui-widget ui-widget-content")
|
||||
.addClass("ui-helper-clearfix ui-corner-all")
|
||||
.find(".portlet-header")
|
||||
.addClass("ui-widget-header ui-corner-all")
|
||||
.prepend('<span class="ui-icon ui-icon-minus"></span>')
|
||||
.end()
|
||||
.find(".portlet-content");
|
||||
|
||||
restoreOrder();
|
||||
|
||||
$(".portlet-header .ui-icon").click(function() {
|
||||
$(this).toggleClass("ui-icon-minus");
|
||||
$(this).toggleClass("ui-icon-plus");
|
||||
$(this).parents(".portlet:first").find(".portlet-content").toggle();
|
||||
saveOrder(); // This is important
|
||||
});
|
||||
|
||||
$( "document" ).ready(function(){
|
||||
if ($.browser.msie) {
|
||||
if ($.browser.version >= 8.0 && $.browser.version < 9.0)
|
||||
{
|
||||
/* scaling bug in IE8.. iframe has to be 4 times bigger */
|
||||
$( "#iframe" ).css('width', 1024 * 4);
|
||||
$( "#iframe" ).css('height', 768 * 4);
|
||||
}
|
||||
$( "#iframe" ).css('zoom', '0.25');
|
||||
}
|
||||
|
||||
{% if countdown_state == "active" %}
|
||||
switchButtons('stop');
|
||||
{% else %}
|
||||
switchButtons('play');
|
||||
{% endif %}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery.form.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -180,56 +68,28 @@
|
||||
<div class="portlet" id="portlet_overlays">
|
||||
<div class="portlet-header">{% trans 'Overlays' %}</div>
|
||||
<div class="portlet-content">
|
||||
<ul style="line-height: 180%">
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<ul>
|
||||
{% for overlay in overlays %}
|
||||
<li>
|
||||
<input type="checkbox" name="{{ overlay.def_name }}" onchange="submit()"
|
||||
{% if overlay.active %} checked="checked"{% endif %}> {{ overlay }}:
|
||||
<a id="{{ overlay.def_name }}_inactive" href="{% url projector_overlay_activate overlay.def_name %}" class="overlay"{% if overlay.active %} style="display:none"{% endif %}>
|
||||
<div></div>
|
||||
</a>
|
||||
<a id="{{ overlay.def_name }}_active" href="{% url projector_overlay_deactivate overlay.def_name %}" class="overlay active"{% if not overlay.active %} style="display:none"{% endif %}>
|
||||
<div></div>
|
||||
</a>
|
||||
|
||||
{{ overlay }}:
|
||||
{# TODO: Call the html via overlay.html #}
|
||||
{# Countdown #}
|
||||
{% if overlay.def_name == "Countdown" %}
|
||||
<span class="projector_countdown_spinbox">
|
||||
<input class="projector_countdown_spinval" id="countdown_time" name="countdown_time" type="number" min="0" value="{{countdown_time}}">{% trans "sec" %}
|
||||
<a id="countdown_set" class="projector_countdown_btn" href="{% url countdown_set_default %}" title="{% trans 'Save as default' %}">
|
||||
<img src="{% static 'images/icons/document-save.png' %}" />
|
||||
</a>
|
||||
|
||||
<a class="projector_countdown_btn" href="{% url countdown_reset %}" title="{% trans 'Reset countdown' %}" onclick="javascript:switchButtons('play')">
|
||||
<button type="submit" class="button" style="padding:4px;" name='message-clean'>
|
||||
<span class="icon backward"> </span>
|
||||
</button></a>
|
||||
<a id="countdown_play" class="projector_countdown_btn" href="{% url countdown_start %}" title="{% trans 'Start countdown' %}" onclick="javascript:switchButtons('stop')"><button
|
||||
type="submit" class="button" style="padding:4px;" name='message-clean'>
|
||||
<span class="icon play"> </span>
|
||||
</button></a>
|
||||
<a id="countdown_stop" class="projector_countdown_btn" href="{% url countdown_stop %}" title="{% trans 'Stop countdown' %}" onclick="javascript:switchButtons('play')">
|
||||
<button type="submit" class="button" style="padding:4px;" name='message-clean'>
|
||||
<span class="icon pause"> </span>
|
||||
</button>
|
||||
</a>
|
||||
</span>
|
||||
<p></p>
|
||||
{% include 'projector/control_countdown.html' %}
|
||||
{% endif %}
|
||||
{% if overlay.def_name == "Message" %}
|
||||
<nobr>
|
||||
<input name='message_text' type='text' style='width: 70%'
|
||||
value="{% get_config 'projector_message' %}">
|
||||
<button type="submit"
|
||||
class="button" style="padding:4px 0;" name='message-clean' title="{% trans 'Clean message' %}">
|
||||
<span class="icon clear"> </span>
|
||||
</button>
|
||||
</nobr>
|
||||
<br>
|
||||
<button type="submit" class="button" name='message'>
|
||||
<span class="icon ok">{% trans 'Apply' %}</span>
|
||||
</button>
|
||||
{% include 'projector/control_overlay_message.html' %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</form>
|
||||
</ul>
|
||||
</div>
|
||||
</div> <!-- end portlet-->
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
{% load staticfiles %}
|
||||
{% load i18n %}
|
||||
{% load tags %}
|
||||
|
||||
<span class="projector_countdown_spinbox">
|
||||
<input class="projector_countdown_spinval" id="countdown_time" name="countdown_time" type="number" min="0" value="{{ countdown_time }}"> {% trans "sec" %}
|
||||
<a id="countdown_set" class="countdown_control" href="{% url countdown_set_default %}" title="{% trans 'Save as default' %}">
|
||||
<img src="{% static 'images/icons/document-save.png' %}" alt="{% url countdown_set_default %}">
|
||||
</a>
|
||||
<a id="countdown_reset" class="countdown_control" href="{% url countdown_reset %}" title="{% trans 'Reset countdown' %}">
|
||||
<img src="{% static 'images/icons/skip-backward.png' %}" alt="{% trans 'Reset countdown' %}">
|
||||
</a>
|
||||
<a id="countdown_play" class="countdown_control" href="{% url countdown_start %}" title="{% trans 'Start countdown' %}"{% if countdown_state == 'active' %} style="display:none"{% endif %}>
|
||||
<img src="{% static 'images/icons/play.png' %}" alt="{% url countdown_start %}">
|
||||
</a>
|
||||
<a id="countdown_stop" class="countdown_control" href="{% url countdown_stop %}" title="{% trans 'Stop countdown' %}"{% if countdown_state == 'inactive' or countdown_state == 'paused' or countdown_state == 'expired' %} style="display:none"{% endif %}>
|
||||
<img src="{% static 'images/icons/pause.png' %}" alt="{% url countdown_stop %}">
|
||||
</a>
|
||||
</span>
|
@ -0,0 +1,14 @@
|
||||
{% load staticfiles %}
|
||||
{% load i18n %}
|
||||
{% load tags %}
|
||||
<form id="overlay-form" action="" method="post" style="display:inline">{% csrf_token %}
|
||||
<input name='message_text' type='text' style='width: 40%' value="{% get_config 'projector_message' %}">
|
||||
<button type="submit" class="button" name='message'>
|
||||
<span class="icon ok">{% trans 'Apply' %}</span>
|
||||
</button>
|
||||
<button type="submit"
|
||||
class="button" style="padding:4px 0;" name='message-clean' title="{% trans 'Clean message' %}">
|
||||
<span class="icon clear"> </span>
|
||||
</button>
|
||||
</form>
|
||||
|
@ -17,8 +17,7 @@ from openslides.utils.views import CreateView
|
||||
from openslides.projector.models import ProjectorSlide
|
||||
from openslides.projector.views import (ControlView, ActivateView,
|
||||
CustomSlideCreateView, CustomSlideUpdateView, CustomSlideDeleteView,
|
||||
CountdownEdit, ProjectorEdit, Projector)
|
||||
|
||||
CountdownEdit, ProjectorEdit, Projector, ActivateOverlay)
|
||||
|
||||
|
||||
urlpatterns = patterns('projector.views',
|
||||
@ -99,20 +98,6 @@ urlpatterns = patterns('projector.views',
|
||||
## name='countdown_edit',
|
||||
## ),
|
||||
|
||||
|
||||
|
||||
url(r'^countdown/show/$',
|
||||
CountdownEdit.as_view(),
|
||||
{'command': 'show'},
|
||||
name='countdown_open',
|
||||
),
|
||||
|
||||
url(r'^countdown/hide/$',
|
||||
CountdownEdit.as_view(),
|
||||
{'command': 'hide'},
|
||||
name='countdown_close',
|
||||
),
|
||||
|
||||
url(r'^countdown/reset/$',
|
||||
CountdownEdit.as_view(),
|
||||
{'command': 'reset'},
|
||||
@ -136,4 +121,16 @@ urlpatterns = patterns('projector.views',
|
||||
{'command': 'set-default'},
|
||||
name='countdown_set_default',
|
||||
),
|
||||
|
||||
url('^overlay/(?P<name>[^/]*)/activate/$',
|
||||
ActivateOverlay.as_view(),
|
||||
{'activate': True},
|
||||
name='projector_overlay_activate',
|
||||
),
|
||||
|
||||
url('^overlay/(?P<name>[^/]*)/deactivate/$',
|
||||
ActivateOverlay.as_view(),
|
||||
{'activate': False},
|
||||
name='projector_overlay_deactivate',
|
||||
),
|
||||
)
|
||||
|
@ -35,7 +35,7 @@ from openslides.projector.models import ProjectorOverlay, ProjectorSlide
|
||||
from openslides.projector.signals import projector_overlays
|
||||
|
||||
|
||||
class ControlView(TemplateView):
|
||||
class ControlView(TemplateView, AjaxMixin):
|
||||
template_name = 'projector/control.html'
|
||||
permission_required = 'projector.can_manage_projector'
|
||||
|
||||
@ -64,6 +64,8 @@ class ControlView(TemplateView):
|
||||
else:
|
||||
overlay.active = False
|
||||
overlay.save()
|
||||
if request.is_ajax():
|
||||
return ajax_get(request, *args, **kwargs)
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@ -94,6 +96,32 @@ class ControlView(TemplateView):
|
||||
return context
|
||||
|
||||
|
||||
class ActivateOverlay(RedirectView):
|
||||
url = 'projector_control'
|
||||
allow_ajax = True
|
||||
|
||||
@property
|
||||
def overlay(self):
|
||||
try:
|
||||
return self._overlay
|
||||
except AttributeError:
|
||||
self._overlay = ProjectorOverlay.objects.get(def_name=self.kwargs['name'])
|
||||
return self._overlay
|
||||
|
||||
def pre_redirect(self, request, *args, **kwargs):
|
||||
if kwargs['activate']:
|
||||
self.overlay.active = True
|
||||
else:
|
||||
self.overlay.active = False
|
||||
self.overlay.save()
|
||||
|
||||
def get_ajax_context(self, **kwargs):
|
||||
return {
|
||||
'active': self.overlay.active,
|
||||
'def_name': self.overlay.def_name,
|
||||
}
|
||||
|
||||
|
||||
class ActivateView(RedirectView):
|
||||
url = 'projector_control'
|
||||
allow_ajax = True
|
||||
@ -244,6 +272,7 @@ class CountdownEdit(RedirectView):
|
||||
|
||||
def pre_redirect(self, request, *args, **kwargs):
|
||||
command = kwargs['command']
|
||||
# countdown_state is one of 'inactive', 'paused' and 'active', 'expired'
|
||||
if command in ['reset', 'start', 'stop']:
|
||||
config['countdown_time'] = config['countdown_time']
|
||||
|
||||
@ -276,6 +305,12 @@ class CountdownEdit(RedirectView):
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def get_ajax_context(self, **kwargs):
|
||||
return {
|
||||
'state': config['countdown_state'],
|
||||
'countdown_time': config['countdown_time'],
|
||||
}
|
||||
|
||||
|
||||
def register_tab(request):
|
||||
selected = True if request.path.startswith('/projector/') else False
|
||||
|
Loading…
Reference in New Issue
Block a user