diff --git a/cmd/console/Action.elm b/cmd/console/Action.elm index 837da7d..f84f0fe 100644 --- a/cmd/console/Action.elm +++ b/cmd/console/Action.elm @@ -18,9 +18,10 @@ type Msg | FetchApps (WebData (List App)) | FetchRule (WebData Rule) | FetchRules (WebData (List Rule)) - | ListApps | LocationChange Location | Navigate Route | NewApp (WebData App) - | SelectApp String + | RuleDeleteAsk String + | RuleDeleteConfirm String + | RuleDelete (WebData Bool) | Tick Time diff --git a/cmd/console/Main.elm b/cmd/console/Main.elm index dfd8fac..79655b5 100644 --- a/cmd/console/Main.elm +++ b/cmd/console/Main.elm @@ -3,6 +3,7 @@ module Main exposing (main) import AnimationFrame import Navigation import Action exposing (Msg(..)) +import Ask exposing (confirm) import Model exposing (Flags, Model, init) import Update exposing (update) import View exposing (view) @@ -18,10 +19,11 @@ main = } - -- SUBSCRIPTION - subscriptions : Model -> Sub Msg subscriptions model = - AnimationFrame.times Tick + Sub.batch + [ AnimationFrame.times Tick + , confirm RuleDeleteConfirm + ] diff --git a/cmd/console/Rule/Api.elm b/cmd/console/Rule/Api.elm index 5d9247e..9c5ee24 100644 --- a/cmd/console/Rule/Api.elm +++ b/cmd/console/Rule/Api.elm @@ -1,13 +1,26 @@ -module Rule.Api exposing (getRule, listRules) +module Rule.Api exposing (deleteRule, getRule, listRules) import Http import RemoteData exposing (WebData, sendRequest) import Rule.Model exposing (Rule, decode, decodeList) +deleteRule : String -> String -> Cmd (WebData Bool) +deleteRule appId ruleId = + Http.request + { body = Http.emptyBody + , expect = Http.expectStringResponse readDelete + , headers = [] + , method = "DELETE" + , timeout = Nothing + , url = ruleUrl appId ruleId + , withCredentials = False + } + |> sendRequest + getRule : String -> String -> Cmd (WebData Rule) getRule appId ruleId = - Http.get ("/api/apps/" ++ appId ++ "/rules/" ++ ruleId) decode + Http.get (ruleUrl appId ruleId) decode |> sendRequest @@ -15,3 +28,14 @@ listRules : String -> Cmd (WebData (List Rule)) listRules appId = Http.get ("/api/apps/" ++ appId ++ "/rules") decodeList |> sendRequest + +readDelete : Http.Response String -> Result String Bool +readDelete response = + if response.status.code == 204 then + Ok True + else + Err response.status.message + +ruleUrl : String -> String -> String +ruleUrl appId ruleId = + "/api/apps/" ++ appId ++ "/rules/" ++ ruleId diff --git a/cmd/console/Rule/Model.elm b/cmd/console/Rule/Model.elm index 4819367..40c4843 100644 --- a/cmd/console/Rule/Model.elm +++ b/cmd/console/Rule/Model.elm @@ -1,4 +1,4 @@ -module Rule.Model exposing (Rule, decode, decodeList, targetString) +module Rule.Model exposing (Entity(..), Rule, decode, decodeList, targetString) import Dict exposing (Dict) import Json.Decode as Decode @@ -6,6 +6,12 @@ import Json.Decode as Decode -- MODEL +type Criteria + = EventCriteria + | ObjectCriteria + +type Entity + = Connection | Event | Object | Reaction | UnknownEntity type alias Recipient = { query : List Query @@ -17,21 +23,40 @@ type alias Recipient = type alias Rule = { active : Bool + , criteria : Criteria , deleted : Bool , ecosystem : Int - , entity : Int + , entity : Entity , id : String , name : String , recipients : List Recipient } type Target - = Commenters | PostOwner | Unknown + = Commenters | PostOwner | UnknownTarget type alias Query = ( String, String ) +matchEntity : Int -> Entity +matchEntity enum = + case enum of + 0 -> + Connection + + 1 -> + Event + + 2 -> + Object + + 3 -> + Reaction + + _ -> + UnknownEntity + matchTarget : Query -> Target matchTarget query = case query of @@ -42,7 +67,7 @@ matchTarget query = PostOwner ( _, _ ) -> - Unknown + UnknownTarget targetString : Target -> String targetString target = @@ -53,7 +78,7 @@ targetString target = PostOwner -> "PostOwner" - Unknown -> + UnknownTarget -> "Unknown" @@ -63,15 +88,21 @@ targetString target = decode : Decode.Decoder Rule decode = - Decode.map7 Rule + Decode.map8 Rule (Decode.field "active" Decode.bool) + (Decode.field "criteria" decodeCriteria) (Decode.field "deleted" Decode.bool) (Decode.field "ecosystem" Decode.int) - (Decode.field "entity" Decode.int) + (Decode.andThen decodeEntity (Decode.field "entity" Decode.int)) (Decode.field "id" Decode.string) (Decode.field "name" Decode.string) (Decode.field "recipients" (Decode.list decodeRecipient)) +decodeCriteria = + Decode.succeed EventCriteria + +decodeEntity raw = + Decode.succeed (matchEntity raw) decodeList : Decode.Decoder (List Rule) decodeList = diff --git a/cmd/console/Rule/View.elm b/cmd/console/Rule/View.elm index 085a080..140ec6e 100644 --- a/cmd/console/Rule/View.elm +++ b/cmd/console/Rule/View.elm @@ -5,6 +5,7 @@ import Html.Attributes exposing (class, title) import Html.Events exposing (onClick) import Rule.Model exposing (Rule) +import Rule.Model exposing (Entity(..)) viewActivated : Bool -> Html msg viewActivated active = @@ -22,22 +23,22 @@ viewEcosystem ecosystem = _ -> span [ class "nc-icon-outline ui-2_alert", title "unknown" ] [] -viewEntity : Int -> Html msg +viewEntity : Entity -> Html msg viewEntity entity = case entity of - 0 -> + Connection -> span [ class "nc-icon-outline arrows-2_conversion", title "Connection" ] [] - 1 -> + Event -> span [ class "nc-icon-outline ui-1_bell-53", title "event" ] [] - 2 -> + Object -> span [ class "nc-icon-outline ui-1_database", title "Object" ] [] - 3 -> + Reaction -> span [ class "nc-icon-outline ui-2_like", title "Reaction" ] [] - _ -> + UnknownEntity -> span [ class "nc-icon-outline ui-2_alert", title "Unknown" ] [] viewRuleDescription : Rule -> Html msg @@ -59,31 +60,31 @@ viewRuleDescription rule = entity = case rule.entity of - 0 -> + Connection -> div [ class "icon", title "Connections" ] [ span [ class "nc-icon-outline arrows-2_conversion" ] [] , span [] [ text "Connections" ] ] - 1 -> + Event -> div [ class "icon", title "Events" ] [ span [ class "nc-icon-outline ui-1_bell-53" ] [] , span [] [ text "Events" ] ] - 2 -> + Object -> div [ class "icon", title "Objects" ] [ span [ class "nc-icon-outline ui-1_database" ] [] , span [] [ text "Objects" ] ] - 3 -> + Reaction -> div [ class "icon", title "Reactions" ] [ span [ class "nc-icon-outline ui-2_like" ] [] , span [] [ text "Reactions" ] ] - _ -> + UnknownEntity -> div [ class "icon", title "Unknown" ] [ span [ class "nc-icon-outline ui-2_alert" ] [] , span [] [ text "Unknown" ] @@ -115,9 +116,9 @@ viewRuleTable : (Rule -> Html msg) -> List Rule -> Html msg viewRuleTable item rules = let list = - List.sortBy .entity rules + List.sortWith sortByEntity rules in - table [] + table [ class "navigation" ] [ thead [] [ tr [] [ th [ class "icon" ] [ text "active" ] @@ -129,3 +130,43 @@ viewRuleTable item rules = ] , tbody [] (List.map item list) ] + + +sortByEntity : Rule -> Rule -> Order +sortByEntity a b = + case (a.entity, b.entity) of + (Connection, Connection) -> + EQ + + (Connection, _) -> + LT + + (Event, Connection) -> + GT + + (Event, Event) -> + EQ + + (Event, _) -> + LT + + (Object, Connection) -> + GT + + (Object, Event) -> + GT + + (Object, Object) -> + EQ + + (Object, _) -> + LT + + (Reaction, Reaction) -> + EQ + + (Reaction, _) -> + GT + + (UnknownEntity, _) -> + GT \ No newline at end of file diff --git a/cmd/console/Update.elm b/cmd/console/Update.elm index 3181492..1b6f1e2 100644 --- a/cmd/console/Update.elm +++ b/cmd/console/Update.elm @@ -2,11 +2,13 @@ module Update exposing (update) import RemoteData exposing (RemoteData(Loading, NotAsked), WebData) import Action exposing (Msg(..)) +import Ask exposing (ask) import Formo exposing (blurElement, elementValue, focusElement, updateElementValue, validateForm) import Model exposing (Flags, Model, init) import App.Api exposing (createApp) import App.Model exposing (initAppForm) import Route +import Rule.Api exposing (deleteRule) update : Msg -> Model -> ( Model, Cmd Msg ) @@ -48,9 +50,6 @@ update msg model = FetchRules response -> ( { model | rules = response }, Cmd.none ) - ListApps -> - ( model, Cmd.map LocationChange (Route.navigate Route.Apps) ) - LocationChange location -> init (Flags model.zone) location @@ -60,8 +59,14 @@ update msg model = NewApp response -> ( { model | appForm = initAppForm, apps = (appendWebData model.apps response), newApp = NotAsked }, Cmd.none ) - SelectApp id -> - ( model, Cmd.map LocationChange (Route.navigate (Route.App id)) ) + RuleDeleteAsk id -> + ( model, ask id ) + + RuleDeleteConfirm id -> + ( model, Cmd.map RuleDelete (deleteRule model.appId id) ) + + RuleDelete _ -> + ( model, Cmd.map LocationChange (Route.navigate (Route.Rules model.appId)) ) Tick time -> let diff --git a/cmd/console/View.elm b/cmd/console/View.elm index 177d403..2e03ee5 100644 --- a/cmd/console/View.elm +++ b/cmd/console/View.elm @@ -56,28 +56,19 @@ view model = pageApp : Model -> Html Msg pageApp { app, startTime, time } = let + viewEntities app = + List.map viewEntity + [ ( app.counts.rules, "Rules", "education_book-39", (Navigate (Route.Rules app.id)) ) + , ( app.counts.users, "Users", "users_multiple-11", (Navigate (Route.Users app.id)) ) + ] + viewApp app = div [] [ h3 [] [ text app.name ] , p [] [ text app.description ] - , ul [ class "entities" ] - [ li [] - [ a [ onClick (Navigate (Route.Rules app.id)), title "Rules" ] - [ span [ class "icon nc-icon-glyph education_book-39" ] [] - , span [] [ text "Rules -" ] - , span [ class "count" ] [ text (toString app.counts.rules) ] - ] - ] - , li [] - [ a [ onClick (Navigate (Route.Users app.id)), title "Rules" ] - [ span [ class "icon nc-icon-glyph users_multiple-11" ] [] - , span [] [ text "Users -" ] - , span [ class "count" ] [ text (toString app.counts.users) ] - ] - ] - ] + , ul [ class "entities" ] (viewEntities app) ] in @@ -92,7 +83,7 @@ pageApps : Model -> Html Msg pageApps { app, apps, appForm, newApp, startTime, time } = let viewItem = - (\app -> viewAppItem (SelectApp app.id) app) + (\app -> viewAppItem (Navigate (Route.App app.id)) app) viewApps apps = if List.length apps == 0 then @@ -178,14 +169,30 @@ pageRule { app, appId, rule, startTime, time } = ] ) , div [ class "templates" ] - [ span [] [ text "Templates: " ] - , strong [] [ text (toString (List.length (Dict.toList recipient.templates))) ] + [ viewTemplates recipient.templates + ] + ] + + viewActions rule = + ul [ class "actions" ] + [ li [] + [ a [] + [ span [ class "icon nc-icon-glyph ui-1_edit-76" ] [] + , span [] [ text "edit" ] + ] + ] + , li [] + [ a [ onClick (RuleDeleteAsk rule.id) ] + [ span [ class "icon nc-icon-glyph ui-1_trash" ] [] + , span [] [ text "delete" ] + ] ] ] viewRule rule = div [] - [ viewRuleDescription rule + [ viewActions rule + , viewRuleDescription rule , h4 [] [ span [ class "icon nc-icon-outline users_mobile-contact" ] [] , span [] [ text "Recipients" ] @@ -256,7 +263,7 @@ viewContextApps app = viewContextRules : String -> WebData Rule -> Html Msg viewContextRules appId rule = let - ( selected, viewRule ) = + ( _, viewRule ) = case rule of Success rule -> ( True, viewSelected (Navigate (Route.Rule appId rule.id)) rule.name ) @@ -264,7 +271,7 @@ viewContextRules appId rule = _ -> ( False, span [] [] ) in - viewContext "Rules" (Navigate (Route.Rules appId)) viewRule selected "education_book-39" + viewContext "Rules" (Navigate (Route.Rules appId)) viewRule False "education_book-39" viewDebug : Model -> Html Msg @@ -273,6 +280,16 @@ viewDebug model = [ text (toString model) ] +viewEntity : ( Int, String, String, Msg ) -> Html Msg +viewEntity ( count, entity, icon, msg ) = + li [] + [ a [ onClick msg, title entity ] + [ div [ class "icon" ] + [ span [ class ("icon nc-icon-glyph " ++ icon) ] [] ] + , div [] [ span [ class "count" ] [ text (toString count) ] ] + , div [] [ span [] [ text entity ] ] + ] + ] viewHeader : String -> Html Msg viewHeader zone = diff --git a/cmd/console/console.go b/cmd/console/console.go index eee9391..b0676cb 100644 --- a/cmd/console/console.go +++ b/cmd/console/console.go @@ -57,7 +57,15 @@ var (