diff of 043664ac71401b22a897d7b61641c190a58a6f4c

043664ac71401b22a897d7b61641c190a58a6f4c
diff --git a/elm-frontti/src/Ajax_cmds.elm b/elm-frontti/src/Ajax_cmds.elm
index 4f69634..effa0dc 100644
--- a/elm-frontti/src/Ajax_cmds.elm
+++ b/elm-frontti/src/Ajax_cmds.elm
@@ -186,3 +186,14 @@ getAdminLogs =
     Http.get
         { url = "/api/logs"
         , expect = Http.expectJson GotAdminLogs (Json.list Logs.decoder)}
+
+saveGroups groups =
+    Http.post
+        { url = "/api/logs/groups"
+        , body = Http.jsonBody <| Logs.groupsEncoder groups
+        , expect = Http.expectWhatever LogGroupsSaved}
+
+getLogGroups =
+    Http.get
+        { url = "/api/logs/groups"
+        , expect = Http.expectJson GotLogGroups Logs.groupsDecoder}
diff --git a/elm-frontti/src/Logs.elm b/elm-frontti/src/Logs.elm
index 4419cc7..e1fe6eb 100644
--- a/elm-frontti/src/Logs.elm
+++ b/elm-frontti/src/Logs.elm
@@ -2,6 +2,7 @@ module Logs exposing (..)
 
 import Article exposing (decodeApply)
 import Json.Decode as Decode exposing (Decoder, succeed)
+import Json.Encode as Json exposing (..)
 import Regex exposing (Regex)
 
 type alias Log =
@@ -32,3 +33,21 @@ parsedGroup_to_group pg =
     
 rowDecoder = Decode.field "row" Decode.string
 decoder = Decode.succeed Log |> decodeApply rowDecoder             
+
+groupEncoder group =
+    object
+        [ ( "name", string group.name)
+        , ( "alarmy", bool group.alarmy)]
+
+groupsEncoder groups =
+    list groupEncoder groups
+
+nameDecoder = Decode.field "name" Decode.string
+alarmyDecoder = Decode.field "alarmy" Decode.bool
+
+groupDecoder = Decode.succeed Group
+               |> decodeApply nameDecoder
+               |> decodeApply alarmyDecoder
+               |> decodeApply (Decode.succeed [])
+
+groupsDecoder = Decode.list groupDecoder
diff --git a/elm-frontti/src/Logviewer.elm b/elm-frontti/src/Logviewer.elm
index d7f1362..03d4832 100644
--- a/elm-frontti/src/Logviewer.elm
+++ b/elm-frontti/src/Logviewer.elm
@@ -37,8 +37,7 @@ listify group
                    else
                        div [] []]]
       , ul []
-          (List.map log_to_list group.members)
-      , div [ class "debug" ] [ text <| Debug.toString group]]
+          (List.map log_to_list group.members)]
 
 parseRegex: Group -> Maybe ParsedGroup
 parseRegex r =
diff --git a/elm-frontti/src/Main.elm b/elm-frontti/src/Main.elm
index a307f28..20289e7 100644
--- a/elm-frontti/src/Main.elm
+++ b/elm-frontti/src/Main.elm
@@ -120,11 +120,13 @@ viewStatePerUrl url =
                                             , getSettings
                                             , getFeeds False 
                                             , getFeedMeta ])
-        RouteParser.Logs -> (Loading, [ getSettings
-                                      , getSession
-                                      , getAdminLogs 
-                                      , getTitles])
-    
+        RouteParser.Logs -> ( (Logs [] [] "")
+                            , [ getSettings
+                              , getSession
+                              , getAdminLogs
+                              , getTitles
+                              , getLogGroups])
+
 init _ url key =
     let (viewstate, cmds) = (viewStatePerUrl url)
         model = initialModel url key viewstate
@@ -718,8 +720,13 @@ update msg model =
         GotAdminLogs result ->
             case result of
                 Ok logs ->
-                    ({ model | view_state = Logs logs [] ""}
-                    , Cmd.none)
+                    case model.view_state of
+                        Logs _ g str ->
+                            ({ model | view_state = Logs logs g str}
+                            , Cmd.none)
+                        _ ->
+                            ( model
+                            , alert "Wrong viewstate again")
                 Err error ->
                     ( { model | view_state = ShowError (errToString error) }
                     , Cmd.none)
@@ -732,28 +739,25 @@ update msg model =
         SaveLogGroup new_potential_regex ->
             case Regex.fromString new_potential_regex of
                 Just _ ->
-                    let new_viewstate =
-                            case model.view_state of
-                                Logs logs groups _ ->
-                                    let group = Logs.str_to_group new_potential_regex
-                                        -- new_groups: List (Maybe Logs.Group)
-                                        new_groups = (group::groups)                                                
-                                    in 
-                                        Logs logs new_groups ""
-                                _ -> model.view_state
-                    in
-                        ({ model | view_state = new_viewstate}
-                        , Cmd.none)
+                    case model.view_state of
+                        Logs logs groups asd ->
+                            let group = Logs.str_to_group new_potential_regex
+                                new_groups = (group::groups) in 
+                            ({ model | view_state = Logs logs new_groups asd }
+                            , saveGroups new_groups)
+                        _ -> ( model
+                             , Cmd.none)
                 Nothing ->
                     ( model
                     , alert <| "Invalid regex " ++ new_potential_regex)
         DeleteLogGroup group ->
             case model.view_state of
                 Logs logs groups current ->
-                    let new_state = Logs logs (List.filter (\g -> g.name /= group) groups) current
+                    let new_groups = (List.filter (\g -> g.name /= group) groups)
+                        new_state = Logs logs new_groups current
                     in
                         ({ model | view_state = new_state}
-                        , Cmd.none)
+                        , saveGroups new_groups)
                 _ -> ( model
                      , Cmd.none)
         SetLogAlarmy group new_alarmy ->
@@ -767,10 +771,33 @@ update msg model =
                     in
                         ({ model
                                | view_state = Logs a new_groups b}
-                        , Cmd.none)
+                        , saveGroups new_groups)
                 _ -> ( model
                      , Cmd.none)
-                           
+        LogGroupsSaved result ->
+            case result of
+                Ok _ -> 
+                    ( model
+                    , Cmd.none)
+                Err err ->
+                    ( model
+                    , alert <| "Saving groups failed " ++ (Debug.toString err))
+        GotLogGroups result ->
+            case result of
+                Ok groups ->
+                    let new_viewstate = 
+                            case model.view_state of
+                                Logs logs _ str -> Logs logs groups str
+                                _ -> model.view_state
+                    in
+                        ({ model
+                             | view_state = new_viewstate}
+                        , case model.view_state of
+                              Logs _ _ _ -> Cmd.none 
+                              _ -> alert "view state is wrong")
+                Err error -> 
+                    ( { model | view_state = ShowError (errToString error) }
+                    , alert "VIHRE")
                     
 doGoHome_ model other_cmds =
     (model, Cmd.batch (List.append [ getSettings
diff --git a/elm-frontti/src/Message.elm b/elm-frontti/src/Message.elm
index 6362e4f..a9ac757 100644
--- a/elm-frontti/src/Message.elm
+++ b/elm-frontti/src/Message.elm
@@ -225,6 +225,8 @@ type Msg
   | SaveLogGroup String
   | DeleteLogGroup String
   | SetLogAlarmy Logs.ParsedGroup Bool
+  | LogGroupsSaved (Result Http.Error ())
+  | GotLogGroups (Result Http.Error (List Logs.Group))
 
 -- ports
 port reallySetupAce : String -> Cmd msg
diff --git a/resources/sql/023-loggroups.sql b/resources/sql/023-loggroups.sql
new file mode 100644
index 0000000..f5591f4
--- /dev/null
+++ b/resources/sql/023-loggroups.sql
@@ -0,0 +1,5 @@
+CREATE TABLE blog.log_group
+(
+  ID SERIAL PRIMARY KEY,
+  name TEXT NOT NULL UNIQUE,
+  alarmy BOOLEAN NOT NULL);
diff --git a/src/migration-list.lisp b/src/migration-list.lisp
index bbc5dd3..69b6d35 100644
--- a/src/migration-list.lisp
+++ b/src/migration-list.lisp
@@ -27,6 +27,7 @@
 (defmigration "020-rss-reader-stuff")
 (defmigration "021-more-rss-reader-stuff")
 (defmigration "022-fix-rss-cache")
+(defmigration "023-loggroups")
 
 (defun prepare-e2e-migration ()
   (postmodern:execute "DELETE FROM blog.Users")
diff --git a/src/routes/settings-routes.lisp b/src/routes/settings-routes.lisp
index 670714f..2ec5783 100644
--- a/src/routes/settings-routes.lisp
+++ b/src/routes/settings-routes.lisp
@@ -61,3 +61,28 @@
 	  (list "no logs found")
 	  (mapcar #'logify)
 	  stringify))))
+
+(defroute post-logs-groups ("/api/logs/groups" :method :post
+					       :decorators (@transaction
+							    @json
+							    @authenticated
+							    (@can? "update-settings"))) ()
+  (let* ((body-str (hunchentoot:raw-post-data :force-text t))
+	 (body (coerce (parse body-str) 'list)))
+    (log:info "Trying to save ~a~%" body-str)
+    (postmodern:execute "DELETE FROM blog.log_group;")
+    (dolist (group body)
+      (postmodern:execute "INSERT INTO blog.log_group (name, alarmy) VALUES ($1, $2)"
+			  (gethash "name" group)
+			  (gethash "alarmy" group)))
+
+    (setf (hunchentoot:return-code*) 204)
+    ""))
+
+(defroute get-logs-groups ("/api/logs/groups" :method :get 
+					       :decorators (@transaction
+							    @json
+							    @authenticated
+							    (@can? "update-settings"))) ()
+  (let ((groups (postmodern:query "SELECT name, alarmy FROM blog.log_group" :array-hash)))
+    (stringify groups)))