return data
def render(self, template_name, content_type='text/html', **context):
+ import motioneye
+
self.set_header('Content-Type', content_type)
context['USER'] = self.current_user
+ context['VERSION'] = motioneye.VERSION
content = template.render(template_name, **context)
self.finish(content)
@BaseHandler.auth(prompt=False)
def current(self, camera_id):
+ self.set_header('Content-Type', 'image/jpeg')
+
camera_config = config.get_camera(camera_id)
if camera_config['@proto'] == 'v4l2':
jpg = mjpgclient.get_jpg(camera_id)
if jpg is None:
return self.finish()
- self.set_header('Content-Type', 'image/jpeg')
self.finish(jpg)
else:
self.finish({})
else:
- self.set_header('Content-Type', 'image/jpeg')
self.finish(jpg)
remote.current_snapshot(
stable = self.get_argument('stable', default='false') == 'true'
versions = update.get_all_versions(stable=stable)
-
- self.finish_json(versions)
+ current_version = update.get_version()
+ update_version = None
+ if versions and update.compare_versions(versions[-1], current_version) > 0:
+ update_version = versions[-1]
+
+ self.finish_json({
+ 'update_version': update_version,
+ 'current_version': current_version
+ })
@BaseHandler.auth(admin=True)
def post(self):
logging.debug('performing update to version %(version)s' % {'version': version})
result = update.perform_update(version)
-
+
return self.finish_json(result)
if stable:
versions = [v for v in versions if v.count('.') == 1]
- versions.sort()
-
- return ['master'] # TODO
- return versions
+ return sorted(versions, cmp=compare_versions)
except Exception as e:
logging.error('could not get versions: %(msg)s' % {'msg': unicode(e)})
margin-top: 3px;
}
+div.update-button {
+ position: relative;
+ width: 4em;
+ height: 1.5em;
+ line-height: 1.5em;
+ text-align: center;
+ margin: 2px 0px;
+ color: white;
+ font-size: 1em;
+ background-color: #317CAD;
+ border-radius: 3px;
+ transition: all 0.1s linear;
+}
+
+div.update-button:HOVER {
+ background-color: #3498db;
+}
+
+div.update-button:ACTIVE {
+ background-color: #317CAD;
+}
+
div.settings-top-bar.open select.video-device {
display: inline;
}
}
div.modal-title-bar {
- height: 1.5em;
+ min-height: 1.5em;
line-height: 1.5em;
text-align: center;
position: relative;
}
div.modal-title-bar {
- height: 2em;
+ min-height: 2em;
line-height: 2em;
}
}
if (data.reload) {
- window.location.reload();
+ window.location.reload(true);
return;
}
});
}
+function doUpdate() {
+ showModalDialog('<div class="modal-progress"></div>');
+ ajax('GET', '/update/?stable=true', null, function (data) {
+ if (data.update_version == null) {
+ runAlertDialog('motionEye is up to date (current version: ' + data.current_version + ')');
+ }
+ else {
+ runConfirmDialog('New version available: ' + data.update_version + '. Update?', function () {
+ showModalDialog('<div class="modal-progress"></div>');
+ ajax('POST', '/update/?version=' + data.update_version, null, function (result) {
+ if (result) {
+ runAlertDialog('motionEye was successfully updated!', function () {
+ window.location.reload(true);
+ });
+ }
+ else {
+ runAlertDialog('Update failed!', function () {
+ window.location.reload(true);
+ });
+ }
+ });
+ });
+ }
+ });
+}
+
/* fetch & push */
/* dialogs */
-function runAlertDialog(message) {
- runModalDialog({title: message, buttons: 'ok'});
+function runAlertDialog(message, onOk) {
+ runModalDialog({title: message, buttons: 'ok', onOk: onOk});
}
function runConfirmDialog(message, onYes) {
}
});
+ /* software update button */
+ $('div#updateButton').click(doUpdate);
+
/* prevent scroll events on settings div from propagating TODO this does not work */
$('div.settings').mousewheel(function (e, d) {
var t = $(this);
var glass = $('div.modal-glass');
var container = $('div.modal-container');
+ if (container.is(':animated')) {
+ return setTimeout(function () {
+ showModalDialog(content, onClose);
+ }, 100);
+ }
+
if (container.is(':visible')) {
/* the modal dialog is already visible,
* we just replace the content */
var glass = $('div.modal-glass');
var container = $('div.modal-container');
+ if (container.is(':animated')) {
+ return setTimeout(function () {
+ hideModalDialog();
+ }, 100);
+ }
+
glass.animate({'opacity': '0'}, 200, function () {
glass.css('display', 'none');
});
if (info.click) {
var oldClick = info.click;
info.click = function () {
+ hideModalDialog();
+
if (oldClick() == false) {
return;
}
-
- hideModalDialog();
};
}
else {
</div>
</div>
<div class="page">
+ {% if USER == 'admin' %}
<div class="settings">
<div class="settings-container">
<div class="settings-section-title"><input type="checkbox" class="styled section general" id="motionEyeSwitch">General Settings</div>
<td class="settings-item-value"><input type="password" class="styled general" id="normalPasswordEntry"></td>
<td><span class="help-mark" title="the password for the surveillance user">?</span></td>
</tr>
+ <tr class="settings-item advanced-setting">
+ <td colspan="100"><div class="settings-item-separator"></div></td>
+ </tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Current Version</span></td>
+ <td class="settings-item-value"><span class="settings-item-label">{{VERSION}}</span></td>
+ <td><span class="help-mark" title="checks for new versions and performs updates">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Software Update</span></td>
+ <td class="settings-item-value"><div class="button update-button" id="updateButton">Check</div></td>
+ <td><span class="help-mark" title="checks for new versions and performs updates">?</span></td>
+ </tr>
</table>
<div class="settings-section-title"><input type="checkbox" class="styled section device" id="videoDeviceSwitch">Video Device</div>
</table>
</div>
</div>
+ {% endif %}
<div class="page-container">
</div>
<div class="footer">