diff of 949e09aa7c95507e99d613cb6614a544929314fd

949e09aa7c95507e99d613cb6614a544929314fd
diff --git a/elm-frontti/src/Ajax_cmds.elm b/elm-frontti/src/Ajax_cmds.elm
index effa0dc..ac13082 100644
--- a/elm-frontti/src/Ajax_cmds.elm
+++ b/elm-frontti/src/Ajax_cmds.elm
@@ -197,3 +197,11 @@ getLogGroups =
     Http.get
         { url = "/api/logs/groups"
         , expect = Http.expectJson GotLogGroups Logs.groupsDecoder}
+
+getTopbarAlarms permissions =
+    if List.member "update-settings" permissions then
+        Http.get
+            { url = "/api/logs/alarm"
+            , expect = Http.expectJson GotTopbarLogAlarm Logs.topbarAlarmDecoder}
+    else
+        Cmd.none
diff --git a/elm-frontti/src/FeedView.elm b/elm-frontti/src/FeedView.elm
index 123b051..aa3b2a3 100644
--- a/elm-frontti/src/FeedView.elm
+++ b/elm-frontti/src/FeedView.elm
@@ -74,9 +74,9 @@ feeds feedReaderState loginstate show_archived settings zone fs new_feed metadat
                                , onClick <| ShowArchivedFeedItems (not show_archived)] []
                        , text "Show read items"]
             , tabs "rss-feed-tab" (readerState_str feedReaderState) Nothing
-                  (Dict.fromList [ ("PerFeed", TabEntry "Group by feed" (perFeedView loginstate settings zone fs new_feed_state) Nothing ["*"])
-                                 , ("SingleFeed", TabEntry "Show all in a feed" (singleFeedView loginstate settings zone fs) Nothing ["*"])
-                                 , ("FeedManager", TabEntry "Manage feeds" (feedmanager settings.time_format zone fs) Nothing ["*"])])
+                  (Dict.fromList [ ("PerFeed", TabEntry "Group by feed" "" (perFeedView loginstate settings zone fs new_feed_state) Nothing ["*"])
+                                 , ("SingleFeed", TabEntry "Show all in a feed" "" (singleFeedView loginstate settings zone fs) Nothing ["*"])
+                                 , ("FeedManager", TabEntry "Manage feeds" "" (feedmanager settings.time_format zone fs) Nothing ["*"])])
                   
             , h3 [] [ text "Add new feed?"]
             , label [ for "name" ] [ text "Feed name" ]
diff --git a/elm-frontti/src/Logs.elm b/elm-frontti/src/Logs.elm
index 1ff7e55..42a481b 100644
--- a/elm-frontti/src/Logs.elm
+++ b/elm-frontti/src/Logs.elm
@@ -55,3 +55,10 @@ groupDecoder = Decode.succeed Group
                |> decodeApply (Decode.succeed [])
 
 groupsDecoder = Decode.list groupDecoder
+
+type alias TopbarAlarm =
+    { alarm: Bool }
+
+alarmDecoder = Decode.field "alarm" Decode.bool
+topbarAlarmDecoder = Decode.succeed TopbarAlarm
+                   |> decodeApply alarmDecoder
diff --git a/elm-frontti/src/Main.elm b/elm-frontti/src/Main.elm
index 20289e7..1dd8b97 100644
--- a/elm-frontti/src/Main.elm
+++ b/elm-frontti/src/Main.elm
@@ -71,7 +71,7 @@ subscriptions _ = Sub.batch
                   , aceStateUpdate AceStateUpdate
                   , excerptCreated ExcerptCreated]
 
-initialModel url key viewstate = Model viewstate Nothing False False [] Nothing LoggedOut key url Nothing Time.utc [] [] Nothing PerFeed Nothing
+initialModel url key viewstate = Model viewstate Nothing False False [] Nothing LoggedOut key url Nothing Time.utc [] [] Nothing PerFeed Nothing False
     
 viewStatePerUrl : Url.Url -> (ViewState, List (Cmd Msg))
 viewStatePerUrl url =
@@ -140,7 +140,6 @@ init _ url key =
 
 -- PORTS --
 port prompt : String -> Cmd msg
-port alert : String -> Cmd msg
 port showPreviousPostsModal: (() -> Cmd msg)
 port closePreviousPostsModal: (() -> Cmd msg)
 port showPreviousPostPreviewModal: (() -> Cmd msg)
@@ -230,9 +229,10 @@ update msg model =
                     if model.view_state == PostEditor then
                         ({ model | loginState = LoggedIn user 
                          , postEditorSettings = Nothing}
-                        , Cmd.none)
+                        , getTopbarAlarms user.permissions)
                     else 
-                        ({model | loginState = LoggedIn user}, Cmd.none)
+                        ({model | loginState = LoggedIn user}
+                        , getTopbarAlarms user.permissions)
                 Err error ->
                     case error of
                         Http.BadStatus status ->
@@ -797,7 +797,15 @@ update msg model =
                               _ -> alert "view state is wrong")
                 Err error -> 
                     ( { model | view_state = ShowError (errToString error) }
-                    , alert "VIHRE")
+                    , Cmd.none)
+        GotTopbarLogAlarm res ->
+            case res of
+                Ok alarm ->
+                    ({ model | ringLogAlarm = alarm.alarm}
+                    , Cmd.none)
+                Err error -> 
+                    ( { model | view_state = ShowError (errToString error) }
+                    , Cmd.none)
                     
 doGoHome_ model other_cmds =
     (model, Cmd.batch (List.append [ getSettings
@@ -938,37 +946,38 @@ view model =
                                                                       LoggedIn usr -> Just usr
                                                                       _ -> Nothing)
                             (Dict.fromList [ ("Blog"
-                                             , TabEntry "Home"
+                                             , TabEntry "Home" ""
                                                  (blog_tab settings model)
                                                  (Just GoHome)
                                                  ["*"])
                                            , ("RssFeeds"
-                                             , TabEntry "RSS Feeds"
+                                             , TabEntry "RSS Feeds" ""
                                                  (rss_tab model settings)
                                                  (Just (PushUrl "/blog/feeds"))
                                                  ["create-post"] ) -- <- TODO make a real permission for rss
                                            , ("ManagePosts"
-                                             , TabEntry "Manage posts"
+                                             , TabEntry "Manage posts" ""
                                                  (postmanager_tab model)
                                                  (Just (PushUrl "/blog/postadmin"))
                                                  ["create-post", "delete-post", "edit-post"])
                                            , ("ManageMedia"
-                                             , TabEntry "Manage media"
+                                             , TabEntry "Manage media" ""
                                                  (mediamanager_tab model)
                                                  (Just (PushUrl "/blog/mediamanager"))
                                                  ["create-post", "delete-post", "edit-post"])
                                            , ("SettingsTab"
-                                             , TabEntry "Settings"
+                                             , TabEntry "Settings" ""
                                                  (settings_tab settings model)
                                                  (Just (PushUrl "/blog/settings"))
                                                  ["update-settings"])
                                            , ("SettingLogs"
-                                             , TabEntry "Logs"
+                                             , TabEntry ("Logs" ++ (if model.ringLogAlarm then " (!!!!!!)" else ""))
+                                                 (if model.ringLogAlarm then " alert " else "")
                                                  (text "in the frontpage these views don't show up anywhere")
                                                  (Just (PushUrl "/blog/logs"))
                                                  ["update-settings"])
                                            , ("PostEditTab"
-                                             , TabEntry "Post editor"
+                                             , TabEntry "Post editor" ""
                                                  (posteditor_tab settings model)
                                                  (Just GenNewPost)
                                              ["create-post", "edit-post"])])
diff --git a/elm-frontti/src/Message.elm b/elm-frontti/src/Message.elm
index a9ac757..649b76d 100644
--- a/elm-frontti/src/Message.elm
+++ b/elm-frontti/src/Message.elm
@@ -137,7 +137,8 @@ type alias Model =
     , searchedPosts : List Article.PreviousArticle
     , new_feed: Maybe Feeds.NewFeed
     , feedReaderState: FeedReaderState
-    , feedMetadata: Maybe Feeds.FeedMetadata}
+    , feedMetadata: Maybe Feeds.FeedMetadata
+    , ringLogAlarm: Bool}
     
 type Msg
   = PageReceived (Result Http.Error P.Page)
@@ -227,10 +228,12 @@ type Msg
   | SetLogAlarmy Logs.ParsedGroup Bool
   | LogGroupsSaved (Result Http.Error ())
   | GotLogGroups (Result Http.Error (List Logs.Group))
+  | GotTopbarLogAlarm (Result Http.Error Logs.TopbarAlarm)
 
 -- ports
 port reallySetupAce : String -> Cmd msg
 port addImgToAce : String -> Cmd msg
+port alert : String -> Cmd msg
 
 -- dumb shit that would deserve its own module
 dangerouslySetInnerHTML: String -> Html.Attribute msg
diff --git a/elm-frontti/src/PostEditor.elm b/elm-frontti/src/PostEditor.elm
index 5b746b2..d813431 100644
--- a/elm-frontti/src/PostEditor.elm
+++ b/elm-frontti/src/PostEditor.elm
@@ -142,7 +142,7 @@ postEditor post tag showImageModal loadedImages draggingImages editorSettings ap
                                                else
                                                    "EditArticle") (Just user)
                     (Dict.fromList [ ("EditArticle"
-                                     , TabEntry "Edit article"
+                                     , TabEntry "Edit article" ""
                                          (editor [ id "editor-post-content"
                                                  , style "background-color" (if draggingImages then "#880088" else "")
                                                  , hijackOn "dragenter" (D.succeed EditorDragEnter)
@@ -153,7 +153,7 @@ postEditor post tag showImageModal loadedImages draggingImages editorSettings ap
                                                  , hijackOn "ready" (D.succeed (RunAce post.content))])
                                              Nothing ["*"])
                                    , ("PreviewArticle"
-                                     , TabEntry "Preview article"
+                                     , TabEntry "Preview article" ""
                                          (Article_view.articleView app_settings loginState tz post)
                                          Nothing ["*"])])
             _ -> div [] [text "You're not logged in"]]
diff --git a/elm-frontti/src/Tab.elm b/elm-frontti/src/Tab.elm
index 3236694..e99186e 100644
--- a/elm-frontti/src/Tab.elm
+++ b/elm-frontti/src/Tab.elm
@@ -9,7 +9,8 @@ import Message exposing (..)
 
 type alias TabEntry =
     { title: String
-    , component: Html Msg
+    , classes: String
+    , component: Html Msg               
     , onclick: Maybe Msg
     , permissions: List String}
 
@@ -36,10 +37,10 @@ tabs tab_id selected_tab usr tabentries =
                                let entry_ = Dict.get id tabentries in
                                case entry_ of
                                    Just entry -> 
-                                       li [ class (if selected_tab == id then "tab-header tab-selected" else "tab-header")
+                                       li [ class <| (if selected_tab == id then "tab-header tab-selected" else "tab-header") ++ " " ++ entry.classes 
                                           , onClick (case entry.onclick of
                                                          Just oc -> oc
-                                                         Nothing -> SelectTab tab_id id)] [ text entry.title]
+                                                         Nothing -> SelectTab tab_id id)] [ text <| entry.title ]
                                    Nothing -> li [] [ text "Unknown tab" ]))
         , case selected_tab_component of
               Just c -> c.component
diff --git a/resources/css/murja.css b/resources/css/murja.css
index 8f6a8dd..107b4cb 100644
--- a/resources/css/murja.css
+++ b/resources/css/murja.css
@@ -404,6 +404,10 @@ header {
     width: 30%;
 }
 
+.alert {
+    color: #F00;
+}
+
 @media only screen and (max-device-width:480px)
 {
     body {
diff --git a/src/routes/settings-routes.lisp b/src/routes/settings-routes.lisp
index 6c8329f..9817c9e 100644
--- a/src/routes/settings-routes.lisp
+++ b/src/routes/settings-routes.lisp
@@ -117,7 +117,34 @@
 	    counts
 	    :initial-value (make-hash-table :test 'equal))))
 
-
+(defun get-alarmy-groups (user-id read-counts groups)
+  (let ((db-counts (db-counts user-id)))
+    (->>
+      groups
+      (remove-if-not (partial #'gethash "alarmy"))
+      (remove-if (lambda (group)
+		   (let ((name (gethash "name" group)))
+		     (= (or (gethash name db-counts) 0)
+			(gethash name read-counts)))))
+      (mapcar (partial #'gethash "name")))))
+
+(defroute get-log-alarms ("/api/logs/alarm" :method :get
+					    :decorators (@transaction
+							 @json
+							 @authenticated
+							 (@can? "update-settings"))) ()
+  ;; hopefully nobody would be stupid enough to cache apis like these
+  ;; but let's be sure 
+  (setf (hunchentoot:header-out "Cache-Control") "no-store")
+  
+  (let* ((user-id (gethash "id" *user*))
+	 (groups (get-groups))
+	 (read-counts (count-reads groups (get-logs)))
+	 (alarmy-groups (get-alarmy-groups user-id read-counts groups)))
+    (format nil "{\"alarm\": ~:[false~;true~]}" alarmy-groups)))
+
+	
+	  
 (defroute get-logs-groups ("/api/logs/groups" :method :get 
 					      :decorators (@transaction
 							   @json
@@ -127,15 +154,7 @@
     (assert user-id)
     (let* ((groups (get-groups))
 	   (read-counts (count-reads groups (get-logs)))
-	   (db-counts (db-counts user-id))
-	   (alarmy-groups (->>
-			    groups
-			    (remove-if-not (partial #'gethash "alarmy"))
-			    (remove-if (lambda (group)
-					 (let ((name (gethash "name" group)))
-					   (= (or (gethash name db-counts) 0)
-					      (gethash name read-counts)))))
-			    (mapcar (partial #'gethash "name")))))
+	   (alarmy-groups (get-alarmy-groups user-id read-counts groups)))
 
       (dolist (group groups)
 	(let ((name (gethash "name" group)))