]> www.vanbest.org Git - motioneye-debian/commitdiff
added support for layout columns prefs
authorCalin Crisan <ccrisan@gmail.com>
Sun, 6 Dec 2015 19:32:17 +0000 (21:32 +0200)
committerCalin Crisan <ccrisan@gmail.com>
Sun, 6 Dec 2015 19:32:17 +0000 (21:32 +0200)
motioneye/handlers.py
motioneye/prefs.py
motioneye/server.py
motioneye/static/css/main.css
motioneye/static/js/main.js
motioneye/templates/main.html

index 28dcef2380a42d7097886cb8aada96b03bb5d918..fec73cb8a3c8828cdacad36644e3218141f9dd82 100644 (file)
@@ -121,8 +121,8 @@ class BaseHandler(RequestHandler):
 
         return None
     
-    def get_pref(self, key, default=None):
-        return prefs.get(self.current_user or 'anonymous', key, default)
+    def get_pref(self, key):
+        return prefs.get(self.current_user or 'anonymous', key)
         
     def set_pref(self, key, value):
         return prefs.set(self.current_user or 'anonymous', key, value)
@@ -1496,10 +1496,10 @@ class ActionHandler(BaseHandler):
 
 
 class PrefsHandler(BaseHandler):
-    def get(self, key):
+    def get(self, key=None):
         self.finish_json(self.get_pref(key))
 
-    def post(self, key):
+    def post(self, key=None):
         try:
             value = json.loads(self.request.body)
 
index f2e00fb5378994888850d6608028bccc44b354cd..35f3e961ccfa4758b6414c6ea7ecd85ef0f6824e 100644 (file)
@@ -23,6 +23,9 @@ import settings
 
 
 _PREFS_FILE_NAME = 'prefs.json'
+_DEFAULT_PREFS = {
+    'layout_columns': 3
+}
 
 _prefs = None
 
@@ -55,7 +58,7 @@ def _load():
             file.close()
             
     else:
-        logging.debug('preferences file "%s" does not exist, using default preferences')
+        logging.debug('preferences file "%s" does not exist, using default preferences' % file_path)
 
 
 def _save():
@@ -81,17 +84,25 @@ def _save():
         file.close()
 
 
-def get(username, key, default=None):
+def get(username, key=None):
     if _prefs is None:
         _load()
 
-    return _prefs.get(username, {}).get(key, default)
+    if key:
+        return _prefs.get(username, {}).get(key, _DEFAULT_PREFS.get(key))
+    
+    else:
+        return _prefs.get(username, _DEFAULT_PREFS)
 
 
 def set(username, key, value):
     if _prefs is None:
         _load()
 
-    _prefs.setdefault(username, {})[key] = value
-    _save()
+    if key:
+        _prefs.setdefault(username, {})[key] = value
+        
+    else:
+        _prefs[username] = value
 
+    _save()
index a9d006d25015b69bd6e95c43c74c25a489ffed9f..3b65296d0bc940de852c4508fb3514373a048ac3 100644 (file)
@@ -177,7 +177,7 @@ handler_mapping = [
     (r'^/movie/(?P<camera_id>\d+)/(?P<op>download|preview|delete)/(?P<filename>.+?)/?$', handlers.MovieHandler),
     (r'^/movie/(?P<camera_id>\d+)/(?P<op>delete_all)/(?P<group>.*?)/?$', handlers.MovieHandler),
     (r'^/action/(?P<camera_id>\d+)/(?P<action>\w+)/?$', handlers.ActionHandler),
-    (r'^/prefs/(?P<key>\w+)/?$', handlers.PrefsHandler),
+    (r'^/prefs/(?P<key>\w+)?/?$', handlers.PrefsHandler),
     (r'^/_relay_event/?$', handlers.RelayEventHandler),
     (r'^/log/(?P<name>\w+)/?$', handlers.LogHandler),
     (r'^/update/?$', handlers.UpdateHandler),
index 2f72dd3d7dd3b4b929f7cb876aa1a3bcd891df46..d614fafa043437618ddc08fae1cee387c78dbb6a 100644 (file)
@@ -172,18 +172,6 @@ div.button.logout-button {
     height: 48px;
 }
 
-body.admin div.logout-button {
-    display: none;
-}
-
-body.admin div.settings-top-bar.closed div.logout-button {
-    display: inline-block;
-}
-
-body:not(.admin) div.settings-top-bar div.logout-button {
-    display: none;
-}
-
 div.button.rem-camera-button {
     display: none;
     border: 1px solid transparent;
@@ -270,10 +258,6 @@ div.settings.open {
     min-width: 360px;
 }
 
-body:not(.admin) div.settings {
-    display: none !important;
-}
-
 div.settings-container {
     position: relative;
     padding-top: 10px;
@@ -308,10 +292,6 @@ div.settings-top-bar.open {
     min-width: 360px;
 }
 
-body:not(.admin) div.settings-top-bar {
-    display: none !important;
-}
-
 div.settings-top-bar.closed div.apply-button {
     display: none !important;
 }
@@ -321,6 +301,9 @@ div.settings-section-title {
     text-align: right;
     background-color: rgba(100, 100, 100, 0.3);
     padding: 5px 0.5em 5px 5px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    user-select: none;
 }
 
 a.settings-section-title {
@@ -1225,6 +1208,12 @@ img.camera-progress {
     div.camera-frame {
         width: 100% !important;
     }
+    
+    #layoutColumnsRow {
+        /* layout columns are ignored on small screens,
+         * so hide the prefs row as well */
+        display: none !important;
+    }
 }
 
 @media all and (max-height: 320px) {
index 37e81e5bc016f499548e8f05dbd0bc4ebd900180..8482c6c972236dc75bf0d510904ceb5ab0ede393 100644 (file)
@@ -693,8 +693,14 @@ function initUI() {
         });
     });
     
-    /* various change handlers */
+    /* prefs change handlers */
+    $('#layoutColumnsSlider').change(function () {
+        var columns = parseInt(this.value);
+        setLayoutColumns(columns);
+        savePrefs();
+    });
     
+    /* various change handlers */
     $('#storageDeviceSelect').change(function () {
         $('#rootDirectoryEntry').val('/');
     });
@@ -1011,6 +1017,11 @@ function updateConfigUI() {
         }
     });
 
+    if (!isAdmin()) {
+        $('#generalSectionDiv').each(markHideLogic);
+        $('#generalSectionDiv').next().each(markHideLogic);
+    }
+
     if ($('#cameraSelect').find('option').length < 2) { /* no camera configured */
         $('#videoDeviceEnabledSwitch').parent().each(markHideLogic);
         $('#videoDeviceEnabledSwitch').parent().nextAll('div.settings-section-title, table.settings').each(markHideLogic);
@@ -1243,6 +1254,29 @@ function configUiValid() {
     return valid;
 }
 
+function prefsUi2Dict() {
+    var dict = {
+        'layout_columns': $('#layoutColumnsSlider').val()
+    };
+
+    return dict;
+}
+
+function dict2PrefsUi(dict) {
+    $('#layoutColumnsSlider').val(dict['layout_columns']);
+
+    updateConfigUI();
+}
+
+function applyPrefs(dict) {
+    setLayoutColumns(dict['layout_columns']);
+}
+
+function savePrefs() {
+    var prefs = prefsUi2Dict();
+    ajax('POST', basePath + 'prefs/', prefs);
+}
+
 function mainUi2Dict() {
     var dict = {
         'show_advanced': $('#showAdvancedSwitch')[0].checked,
@@ -2549,6 +2583,9 @@ function fetchCurrentConfig(onFetch) {
                     /* normal user with no cameras doesn't make too much sense - force login */
                     doLogout();
                 }
+                
+                $('#cameraSelect').hide();
+                $('#remCameraButton').hide();
 
                 if (onFetch) {
                     onFetch(data);
@@ -2571,21 +2608,32 @@ function fetchCurrentConfig(onFetch) {
     /* add a progress indicator */
     getPageContainer().append('<img class="main-loading-progress" src="' + staticPath + 'img/main-loading-progress.gif">');
 
-    if (isAdmin()) {
-        /* fetch the main configuration */
-        ajax('GET', basePath + 'config/main/get/', null, function (data) {
-            if (data == null || data.error) {
-                showErrorMessage(data && data.error);
-                return;
-            }
-            
-            dict2MainUi(data);
+    /* fetch the prefs */
+    ajax('GET', basePath + 'prefs/', null, function (data) {
+        if (data == null || data.error) {
+            showErrorMessage(data && data.error);
+            return;
+        }
+        
+        dict2PrefsUi(data);
+        applyPrefs(data);
+
+        if (isAdmin()) {
+            /* fetch the main configuration */
+            ajax('GET', basePath + 'config/main/get/', null, function (data) {
+                if (data == null || data.error) {
+                    showErrorMessage(data && data.error);
+                    return;
+                }
+                
+                dict2MainUi(data);
+                fetchCameraList();
+            });
+        }
+        else {
             fetchCameraList();
-        });
-    }
-    else {
-        fetchCameraList();
-    }
+        }
+    });
 }
 
 function fetchCurrentCameraConfig(onFetch) {
@@ -3813,7 +3861,7 @@ function addCameraFrameUi(cameraConfig) {
     var cameraImg = cameraFrameDiv.find('img.camera');
     var progressImg = cameraFrameDiv.find('img.camera-progress');
     
-    /* no camera buttons if not admin */
+    /* no configure button unless admin */
     if (!isAdmin()) {
         configureButton.hide();
     }
index a28d830c83dc67937db982bb3aa9deb2490562fc..f7664ce972a2a20915a33ac48c3cfdc33fdcf60a 100644 (file)
@@ -84,7 +84,6 @@
                 <div class="button apply-button" id="applyButton">Apply</div>
                 {% if hostname %}<div class="hostname">{{hostname}}</div>{% endif %}
             </div>
-            <div class="button logout-button mouse-effect" title="switch user"></div>
             <div class="logo">
                 <a href="/">
                     <span class="logo">motionEye</span>
     <div class="page">
         <div class="settings closed">
             <div class="settings-container">
+                <!-- Preferences -->
+                <div class="settings-section-title" id="preferencesDiv">
+                    <span class="help-mark" title="user preferences">?</span>
+                    <a class="settings-section-title">Preferences</a>
+                    <span class="minimize open"></span>
+                </div>
+                <table class="settings">
+                    <tr class="settings-item" min="1" max="4" snap="1" ticksnum="4" decimals="0" id="layoutColumnsRow">
+                        <td class="settings-item-label"><span class="settings-item-label">Layout Columns</span></td>
+                        <td class="settings-item-value"><input type="text" class="range styled prefs" id="layoutColumnsSlider"></td>
+                        <td><span class="help-mark" title="configures the number of columns to use when laying out the camera frames">?</span></td>
+                    </tr>
+                </table>
                 
                 <!-- General Settings -->
-                <div class="settings-section-title">
+                <div class="settings-section-title" id="generalSectionDiv">
                     <span class="help-mark" title="general settings, not related to any camera">?</span>
                     <a class="settings-section-title">General Settings</a>
                     <span class="minimize open"></span>
                 </tr>
                 
                 <!-- Video Device -->
-                <div class="settings-section-title">
+                <div class="settings-section-title" id="deviceSectionDiv">
                     <input type="checkbox" class="styled section device camera-config" id="videoDeviceEnabledSwitch">
                     <span class="help-mark" title="enable this if you want to use this camera device">?</span>
                     <a class="settings-section-title">Video Device</a>
                 </table>
                 
                 <!-- File Storage -->
-                <div class="settings-section-title advanced-setting">
+                <div class="settings-section-title advanced-setting" id="storageSectionDiv">
                     <span class="help-mark" title="choose where and how your media files are saved">?</span>
                     <a class="settings-section-title">File Storage</a>
                     <span class="minimize"></span>
                 </table>
                 
                 <!-- Text Overlay -->
-                <div class="settings-section-title advanced-setting">
+                <div class="settings-section-title advanced-setting" id="textOverlaySectionDiv">
                     <input type="checkbox" class="styled section text-overlay camera-config" id="textOverlayEnabledSwitch">
                     <span class="help-mark" title="choose what information is displayed on the captured frames">?</span>
                     <a class="settings-section-title">Text Overlay</a>
                 </table>
 
                 <!-- Video Streaming -->
-                <div class="settings-section-title" minimize-switch-independent="true">
+                <div class="settings-section-title" minimize-switch-independent="true" id="streamingSectionDiv">
                     <input type="checkbox" class="styled section streaming camera-config" id="videoStreamingEnabledSwitch">
                     <span class="help-mark" title="enable this if you want video streaming for this camera">?</span>
                     <a class="settings-section-title">Video Streaming</a>
                 </table>
                 
                 <!-- Still Images -->
-                <div class="settings-section-title">
+                <div class="settings-section-title" id="stillImagesSectionDiv">
                     <input type="checkbox" class="styled section still-images camera-config" id="stillImagesEnabledSwitch">
                     <span class="help-mark" title="enable this if you want to capture still images (pictures)">?</span>
                     <a class="settings-section-title">Still Images</a>
                 </table>
                 
                 <!-- Movies -->
-                <div class="settings-section-title">
+                <div class="settings-section-title" id="moviesSectionDiv">
                     <input type="checkbox" class="styled section movies camera-config" id="moviesEnabledSwitch">
                     <span class="help-mark" title="enable this if you want to record movies">?</span>
                     <a class="settings-section-title">Movies</a>
                 </table>
 
                 <!-- Motion Detection -->
-                <div class="settings-section-title advanced-setting">
+                <div class="settings-section-title advanced-setting" id="motionDetectionSectionDiv">
                     <input type="checkbox" class="styled section motion-detection camera-config" id="motionDetectionEnabledSwitch">
                     <span class="help-mark" title="enable this to use and configure the motion detection mechanism">?</span>
                     <a class="settings-section-title">Motion Detection</a>
                 </table>
                 
                 <!-- Motion Notifications -->
-                <div class="settings-section-title advanced-setting">
+                <div class="settings-section-title advanced-setting" id="notificationsSectionDiv">
                     <span class="help-mark" title="enable this if you want to be notified when motion is detected">?</span>
                     <a class="settings-section-title">Motion Notifications</a>
                     <span class="minimize"></span>
                 </table>
 
                 <!-- Working Schedule -->
-                <div class="settings-section-title" depends="motionDetectionEnabled">
+                <div class="settings-section-title" depends="motionDetectionEnabled" id="workingScheduleSectionDiv">
                     <input type="checkbox" class="styled section working-schedule camera-config" id="workingScheduleEnabledSwitch">
                     <span class="help-mark" title="enable this if you want to define a weekly working schedule for motion detection">?</span>
                     <a class="settings-section-title">Working Schedule</a>