Fixed bug #790382 by using the Mako template engine to pass Python variables into the template and tweaking a few things in the JS.

bzr-revno: 1599
This commit is contained in:
Raoul Snyman 2011-05-31 20:57:59 +02:00
commit d4a75148b8
6 changed files with 117 additions and 59 deletions

View File

@ -27,91 +27,109 @@
-->
<head>
<meta charset="utf-8" />
<title>OpenLP 2.0 Remote</title>
<title>${app_title}</title>
<link rel="stylesheet" href="/files/jquery.mobile.css" />
<link rel="stylesheet" href="/files/openlp.css" />
<script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/openlp.js"></script>
<script type="text/javascript" src="/files/jquery.mobile.js"></script>
<script type="text/javascript">
translationStrings = {
"go_live": "${go_live}",
"add_to_service": "${add_to_service}",
"no_results": "${no_results}",
"back": "${back}"
}
</script>
</head>
<body>
<div data-role="page" id="home">
<div data-role="header">
<h1>OpenLP 2.0 Remote</h1>
<h1>${app_title}</h1>
</div>
<div data-role="content">
<div data-role="controlgroup">
<a href="#service-manager" data-role="button" data-icon="arrow-r" data-iconpos="right">Service Manager</a>
<a href="#slide-controller" data-role="button" data-icon="arrow-r" data-iconpos="right">Slide Controller</a>
<a href="#alerts" data-role="button" data-icon="arrow-r" data-iconpos="right">Alerts</a>
<a href="#search" data-role="button" data-icon="arrow-r" data-iconpos="right">Search</a>
<a href="#service-manager" data-role="button" data-icon="arrow-r" data-iconpos="right">${service_manager}</a>
<a href="#slide-controller" data-role="button" data-icon="arrow-r" data-iconpos="right">${slide_controller}</a>
<a href="#alerts" data-role="button" data-icon="arrow-r" data-iconpos="right">${alerts}</a>
<a href="#search" data-role="button" data-icon="arrow-r" data-iconpos="right">${search}</a>
</div>
</div>
</div>
<div data-role="page" id="service-manager">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Service Manager</h1>
<a href="#" id="service-refresh" data-role="button" data-icon="refresh">Refresh</a>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${service_manager}</h1>
<a href="#" id="service-refresh" data-role="button" data-icon="refresh">${refresh}</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
</ul>
</div>
<div data-role="footer" data-theme="b" class="ui-bar">
<a href="#" id="service-blank" data-role="button" data-icon="blank">Blank</a>
<a href="#" id="service-unblank" data-role="button" data-icon="unblank">Show</a>
<a href="#" id="service-previous" data-role="button" data-icon="arrow-l">Prev</a>
<a href="#" id="service-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
<a href="#" id="service-blank" data-role="button" data-icon="blank">${blank}</a>
<a href="#" id="service-unblank" data-role="button" data-icon="unblank">${show}</a>
<a href="#" id="service-previous" data-role="button" data-icon="arrow-l">${prev}</a>
<a href="#" id="service-next" data-role="button" data-icon="arrow-r" data-iconpos="right">${next}</a>
</div>
</div>
<div data-role="page" id="slide-controller">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Slide Controller</h1>
<a href="#" id="controller-refresh" data-role="button" data-icon="refresh">Refresh</a>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${slide_controller}</h1>
<a href="#" id="controller-refresh" data-role="button" data-icon="refresh">${refresh}</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
</ul>
</div>
<div data-role="footer" data-theme="b" class="ui-bar">
<a href="#" id="controller-blank" data-role="button" data-icon="blank">Blank</a>
<a href="#" id="controller-unblank" data-role="button" data-icon="unblank">Show</a>
<a href="#" id="controller-previous" data-role="button" data-icon="arrow-l">Prev</a>
<a href="#" id="controller-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
<a href="#" id="controller-blank" data-role="button" data-icon="blank">${blank}</a>
<a href="#" id="controller-unblank" data-role="button" data-icon="unblank">${show}</a>
<a href="#" id="controller-previous" data-role="button" data-icon="arrow-l">${prev}</a>
<a href="#" id="controller-next" data-role="button" data-icon="arrow-r" data-iconpos="right">${next}</a>
</div>
</div>
<div data-role="page" id="alerts">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Alerts</h1>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${alerts}</h1>
</div>
<div data-role="content">
<div data-role="fieldcontain">
<label for="alert-text">Text:</label>
<label for="alert-text">${text}:</label>
<input type="text" name="alert-text" id="alert-text" value="" />
</div>
<a href="#" id="alert-submit" data-role="button">Show Alert</a>
<a href="#" id="alert-submit" data-role="button">${show_alert}</a>
</div>
</div>
<div data-role="page" id="search">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Search</h1>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${search}</h1>
</div>
<div data-role="content">
<div data-role="fieldcontain">
<label for="search-plugin">Search:</label>
<label for="search-plugin">${search}:</label>
<select name="search-plugin" id="search-plugin" data-native-menu="false"></select>
</div>
<div data-role="fieldcontain">
<label for="search-text">Text:</label>
<label for="search-text">${text}:</label>
<input type="search" name="search-text" id="search-text" value="" />
</div>
<a href="#" id="search-submit" data-role="button">Search</a>
<a href="#" id="search-submit" data-role="button">${search}</a>
<ul data-role="listview" data-inset="true">
</div>
</div>
<div data-role="page" id="options">
<div data-role="header" data-position="inline" data-theme="b">
<h1>${options}</h1>
</div>
<div data-role="content">
<input type="hidden" id="selected-item" value="" />
<a href="#" id="go-live" data-role="button">${go_live}</a>
<a href="#" id="add-to-service" data-role="button">${add_to_service}</a>
</div>
</div>
</body>
</html>

0
openlp/plugins/remotes/html/json2.js Executable file → Normal file
View File

View File

@ -47,7 +47,7 @@ window.OpenLP = {
var select = $("#search-plugin");
select.html("");
$.each(data.results.items, function (idx, value) {
select.append("<option value='" + value + "'>" + value + "</option>");
select.append("<option value='" + value[0] + "'>" + value[1] + "</option>");
});
select.selectmenu("refresh");
}
@ -215,16 +215,15 @@ window.OpenLP = {
var ul = $("#search > div[data-role=content] > ul[data-role=listview]");
ul.html("");
if (data.results.items.length == 0) {
var li = $("<li data-icon=\"false\">").text('No results');
var li = $("<li data-icon=\"false\">").text(translationStrings["no_results"]);
ul.append(li);
}
else {
$.each(data.results.items, function (idx, value) {
var item = $("<li>").text(value[1]);
var golive = $("<a href=\"#\">Go Live</a>").attr("value", value[0]).click(OpenLP.goLive);
var additem = $("<a href=\"#\">Add To Service</a>").attr("value", value[0]).click(OpenLP.addToService);
item.append($("<ul>").append($("<li>").append(golive)).append($("<li>").append(additem)));
ul.append(item);
ul.append($("<li>").append($("<a>").attr("href", "#options")
.attr("data-rel", "dialog").attr("data-transition", "pop")
.attr("value", value[0]).click(OpenLP.showOptions)
.text(value[1])));
});
}
ul.listview("refresh");
@ -232,19 +231,23 @@ window.OpenLP = {
);
return false;
},
showOptions: function (event) {
var element = OpenLP.getElement(event);
console.log(element);
$("#selected-item").val(element.attr("value"));
},
goLive: function (event) {
var item = OpenLP.getElement(event);
var id = item.attr("value");
var id = $("#selected-item").val();
var text = JSON.stringify({"request": {"id": id}});
$.getJSON(
"/api/" + $("#search-plugin").val() + "/live",
{"data": text})
$.mobile.changePage("slide-controller");
{"data": text}
);
$.mobile.changePage("#slide-controller");
return false;
},
addToService: function (event) {
var item = OpenLP.getElement(event);
var id = item.attr("value");
var id = $("#selected-item").val();
var text = JSON.stringify({"request": {"id": id}});
$.getJSON(
"/api/" + $("#search-plugin").val() + "/add",
@ -253,6 +256,7 @@ window.OpenLP = {
history.back();
}
);
$("#options").dialog("close");
return false;
}
}
@ -274,6 +278,8 @@ $("#controller-unblank").live("click", OpenLP.unblankDisplay);
$("#alert-submit").live("click", OpenLP.showAlert);
// Search
$("#search-submit").live("click", OpenLP.search);
$("#go-live").live("click", OpenLP.goLive);
$("#add-to-service").live("click", OpenLP.addToService);
// Poll the server twice a second to get any updates.
OpenLP.getSearchablePlugins();
$.ajaxSetup({ cache: false });

View File

@ -6,8 +6,8 @@
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode #
# Woldsund #
# --------------------------------------------------------------------------- #
@ -27,12 +27,13 @@
-->
<head>
<meta charset="utf-8" />
<title>OpenLP 2.0 Stage View</title>
<title>${stage_title}</title>
<link rel="stylesheet" href="/files/stage.css" />
<script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/stage.js"></script>
</head>
<body>
<input type="hidden" id="next-text" value="${next}" />
<div id="right">
<div id="clock"></div>
<div id="notes"></div>

View File

@ -100,24 +100,24 @@ window.OpenLP = {
$("#tag" + OpenLP.currentTags[OpenLP.currentSlide]).addClass("currenttag");
var slide = OpenLP.currentSlides[OpenLP.currentSlide];
var text = slide["text"];
text = text.replace(/\n/g, '<br />');
text = text.replace(/\n/g, "<br />");
$("#currentslide").html(text);
text = "";
if (OpenLP.currentSlide < OpenLP.currentSlides.length - 1) {
for (var idx = OpenLP.currentSlide + 1; idx < OpenLP.currentSlides.length; idx++) {
if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1])
text = text + '<p class="nextslide">';
text = text + "<p class=\"nextslide\">";
text = text + OpenLP.currentSlides[idx]["text"];
if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1])
text = text + '</p>';
text = text + "</p>";
else
text = text + '<br />';
text = text + "<br />";
}
text = text.replace(/\n/g, '<br />');
text = text.replace(/\n/g, "<br />");
$("#nextslide").html(text);
}
else {
text = '<p class="nextslide">Next: ' + OpenLP.nextSong + '</p>';
text = "<p class=\"nextslide\">" + $("#next-text").val() + ": " + OpenLP.nextSong + "</p>";
$("#nextslide").html(text);
}
},

View File

@ -115,7 +115,6 @@ import logging
import os
import urlparse
import re
from pprint import pformat
try:
import json
@ -123,10 +122,11 @@ except ImportError:
import simplejson as json
from PyQt4 import QtCore, QtNetwork
from mako.template import Template
from openlp.core.lib import Receiver, PluginStatus
from openlp.core.lib import Receiver, PluginStatus, StringContent
from openlp.core.ui import HideMode
from openlp.core.utils import AppLocation
from openlp.core.utils import AppLocation, translate
log = logging.getLogger(__name__)
@ -261,6 +261,7 @@ class HttpConnection(object):
self.ready_read)
QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'disconnected()'),
self.disconnected)
self.translate()
def _get_service_items(self):
service_items = []
@ -280,6 +281,31 @@ class HttpConnection(object):
})
return service_items
def translate(self):
"""
Translate various strings in the mobile app.
"""
self.template_vars = {
'app_title': translate('RemotePlugin.Mobile', 'OpenLP 2.0 Remote'),
'stage_title': translate('RemotePlugin.Mobile', 'OpenLP 2.0 Stage View'),
'service_manager': translate('RemotePlugin.Mobile', 'Service Manager'),
'slide_controller': translate('RemotePlugin.Mobile', 'Slide Controller'),
'alerts': translate('RemotePlugin.Mobile', 'Alerts'),
'search': translate('RemotePlugin.Mobile', 'Search'),
'back': translate('RemotePlugin.Mobile', 'Back'),
'refresh': translate('RemotePlugin.Mobile', 'Refresh'),
'blank': translate('RemotePlugin.Mobile', 'Blank'),
'show': translate('RemotePlugin.Mobile', 'Show'),
'prev': translate('RemotePlugin.Mobile', 'Prev'),
'next': translate('RemotePlugin.Mobile', 'Next'),
'text': translate('RemotePlugin.Mobile', 'Text'),
'show_alert': translate('RemotePlugin.Mobile', 'Show Alert'),
'go_live': translate('RemotePlugin.Mobile', 'Go Live'),
'add_to_service': translate('RemotePlugin.Mobile', 'Add To Service'),
'no_results': translate('RemotePlugin.Mobile', 'No Results'),
'options': translate('RemotePlugin.Mobile', 'Options')
}
def ready_read(self):
"""
Data has been sent from the client. Respond to it
@ -327,8 +353,11 @@ class HttpConnection(object):
if not path.startswith(self.parent.html_dir):
return HttpResponse(code=u'404 Not Found')
ext = os.path.splitext(filename)[1]
html = None
if ext == u'.html':
mimetype = u'text/html'
variables = self.template_vars
html = Template(filename=path, input_encoding=u'utf-8', output_encoding=u'utf-8').render(**variables)
elif ext == u'.css':
mimetype = u'text/css'
elif ext == u'.js':
@ -343,9 +372,12 @@ class HttpConnection(object):
mimetype = u'text/plain'
file_handle = None
try:
file_handle = open(path, u'rb')
log.debug(u'Opened %s' % path)
content = file_handle.read()
if html:
content = html
else:
file_handle = open(path, u'rb')
log.debug(u'Opened %s' % path)
content = file_handle.read()
except IOError:
log.exception(u'Failed to open %s' % path)
return HttpResponse(code=u'404 Not Found')
@ -460,7 +492,8 @@ class HttpConnection(object):
for plugin in self.parent.plugin.pluginManager.plugins:
if plugin.status == PluginStatus.Active and \
plugin.mediaItem and plugin.mediaItem.hasSearch:
searches.append(plugin.name)
searches.append([plugin.name, unicode(
plugin.textStrings[StringContent.Name][u'plural'])])
return HttpResponse(
json.dumps({u'results': {u'items': searches}}),
{u'Content-Type': u'application/json'})
@ -476,7 +509,7 @@ class HttpConnection(object):
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and \
plugin.mediaItem and plugin.mediaItem.hasSearch:
results =plugin.mediaItem.search(text)
results = plugin.mediaItem.search(text)
else:
results = []
return HttpResponse(