Created
July 12, 2018 05:52
-
-
Save Agnishom/1cd540c83195de2138b093259858f7d9 to your computer and use it in GitHub Desktop.
elm-ui
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module AnalyticPage exposing (..) | |
| import AutoGen exposing (..) | |
| import Navigation | |
| import Http | |
| import Array | |
| import Html exposing (..) | |
| import Html.Attributes exposing (..) | |
| import FileReader | |
| import Json.Decode | |
| import Json.Encode | |
| import Bootstrap.Grid as Grid | |
| import Bootstrap.Grid.Row as Row | |
| import Bootstrap.Grid.Col as Col | |
| import Bootstrap.Card as Card | |
| import Bootstrap.Card.Block as Block | |
| import Bootstrap.Button as Button | |
| import Bootstrap.Badge as Badge | |
| import Bootstrap.ListGroup as ListGroup | |
| import Bootstrap.Form as Form | |
| import Bootstrap.Form.Input as Input | |
| import Bootstrap.Form.Select as Select | |
| import Bootstrap.Utilities.Spacing as Spacing | |
| import Bootstrap.Form.Checkbox as Checkbox | |
| import Bootstrap.Alert as Alert | |
| import Bootstrap.Text as Text | |
| import Ace | |
| type alias Model = | |
| { pageState : Maybe AnalyticPageState | |
| , snippets : List ConvenientSnippet | |
| , files: List FileReader.NativeFile -- the list of files to be uploaded on pressing save | |
| , propro : Bool | |
| } | |
| type HeaderFooter = Header | Footer | |
| type alias ConvenientSnippet = | |
| { headerFooter : HeaderFooter | |
| , conditionalSnippet : ConditionalSnippet | |
| } | |
| init : (Model, Cmd Msg) | |
| init = | |
| { pageState = Nothing | |
| , snippets = [] | |
| , files = [] | |
| , propro = False | |
| } ! [getState] | |
| type Msg | |
| = AddSnippet | |
| | RemoveSnippet Int | |
| | ChangeConditionKind Int String | |
| | ChangeConditionString Int String | |
| | ChangeHF Int HeaderFooter | |
| | ChangeSnippet Int String | |
| | ChangeGlobalHeader String | |
| | ChangeGlobalFooter String | |
| | AddFiles (List FileReader.NativeFile) | |
| | RemoveFile Int -- this is supposed to remove a file from the "to be uploaded" list of files and NOT the already uploaded files | |
| | Save | |
| | Reload String (Result Http.Error Bool) | |
| | UpdatePageState (Result Http.Error AnalyticPageState) | |
| | SnippetSource String | |
| | ToggleProNess | |
| view : Model -> Html Msg | |
| view model = div [] | |
| <| thisisgoingtobethemostawesomeanalyticspagever model | |
| update : Msg -> Model -> (Model, Cmd Msg) | |
| update msg model = case msg of | |
| Reload url (Ok _) -> model ! [Navigation.load url] | |
| Reload url (Err e) -> (Debug.log ("Error in Reload" ++ (toString e)) model) ! [] | |
| UpdatePageState (Ok pageState) -> {model | pageState = Just pageState, snippets = populateSnippets pageState } ! [] | |
| UpdatePageState (Err e) -> (Debug.log ("Error in UpdatePageState" ++ (toString e)) model) ! [] | |
| AddSnippet -> ({ model | snippets = model.snippets ++ [defaultSnippet] }, Cmd.none) | |
| RemoveSnippet j -> (removeSnippet j model) ! [] | |
| ChangeHF j hf -> (changeHF j hf model) ! [] | |
| ChangeSnippet j s -> (changeSnippet j s model) ! [] | |
| ChangeConditionString j s -> (changeConditionString j s model) ! [] | |
| ChangeConditionKind j s -> (changeConditionKind j s model) ! [] | |
| ChangeGlobalHeader s -> (changeGlobalHeader s model) ! [] | |
| ChangeGlobalFooter s -> (changeGlobalFooter s model) ! [] | |
| AddFiles files -> (addFiles files model) ! [] | |
| RemoveFile j -> (removeFile j model) ! [] | |
| ToggleProNess -> ({ model | propro = not model.propro }, Cmd.none) | |
| Save -> model ! [save model] | |
| _ -> (model, Cmd.none) | |
| removeFile : Int -> Model -> Model | |
| removeFile j model = | |
| let | |
| files = Array.toIndexedList <| Array.fromList model.files | |
| newFiles = List.map Tuple.second <| List.filter (\(i, s) -> i /= j) files | |
| in | |
| { model | files = newFiles } | |
| addFiles : List FileReader.NativeFile -> Model -> Model | |
| addFiles files model = | |
| let | |
| newFiles = model.files ++ files | |
| -- newFileNames = List.map (\file -> "/" ++ file.name) files | |
| -- newPageState = | |
| -- case model.pageState of | |
| -- Just state -> | |
| -- let | |
| -- oldSettings = state.analytic_settings | |
| -- oldFileNames = oldSettings.file_names | |
| -- in | |
| -- Just <| { state | | |
| -- analytic_settings = | |
| -- { oldSettings | | |
| -- file_names = | |
| -- oldFileNames ++ newFileNames | |
| -- } | |
| -- } | |
| -- Nothing -> Nothing | |
| in | |
| { model | files = newFiles } | |
| extractString : UrlMatchingCondition -> String | |
| extractString urlmatchingcondition = | |
| case urlmatchingcondition of | |
| UMStartsWith s -> s | |
| UMEndsWith s -> s | |
| UMDoesNotStartWith s -> s | |
| UMDoesNotEndWith s -> s | |
| UMContains s -> s | |
| UMDoesNotContain s -> s | |
| UMMatchesRegex s -> s | |
| UMDoesNotMatchRegex s -> s | |
| changeConditionKind : Int -> String -> Model -> Model | |
| changeConditionKind i s model = | |
| let | |
| snippets = Array.toIndexedList <| Array.fromList model.snippets | |
| f snip = | |
| let | |
| oldConditionalSnippet = snip.conditionalSnippet | |
| newCondition = | |
| case s of | |
| "UMStartsWith" -> UMStartsWith (extractString oldConditionalSnippet.condition) | |
| "UMEndsWith" -> UMEndsWith (extractString oldConditionalSnippet.condition) | |
| "UMDoesNotStartWith" -> UMDoesNotStartWith (extractString oldConditionalSnippet.condition) | |
| "UMDoesNotEndWith" -> UMDoesNotEndWith (extractString oldConditionalSnippet.condition) | |
| "UMContains" -> UMContains (extractString oldConditionalSnippet.condition) | |
| "UMDoesNotContain" -> UMDoesNotContain (extractString oldConditionalSnippet.condition) | |
| "UMMatchesRegex" -> UMMatchesRegex (extractString oldConditionalSnippet.condition) | |
| "UMDoesNotMatchRegex" -> UMDoesNotMatchRegex (extractString oldConditionalSnippet.condition) | |
| _ -> UMStartsWith "Error" | |
| in | |
| { snip | conditionalSnippet = { oldConditionalSnippet | condition = newCondition } } | |
| newSnippets = List.map (\(j, s) -> if i == j then f s else s) snippets | |
| in | |
| { model | snippets = newSnippets } | |
| changeConditionString : Int -> String -> Model -> Model | |
| changeConditionString i s model = | |
| let | |
| snippets = Array.toIndexedList <| Array.fromList model.snippets | |
| f snip = | |
| let | |
| oldConditionalSnippet = snip.conditionalSnippet | |
| newCondition = | |
| case oldConditionalSnippet.condition of | |
| UMStartsWith _ -> UMStartsWith s | |
| UMEndsWith _ -> UMEndsWith s | |
| UMDoesNotStartWith _ -> UMDoesNotStartWith s | |
| UMDoesNotEndWith _ -> UMDoesNotEndWith s | |
| UMContains _ -> UMContains s | |
| UMDoesNotContain _ -> UMDoesNotContain s | |
| UMMatchesRegex _ -> UMMatchesRegex s | |
| UMDoesNotMatchRegex _ -> UMDoesNotMatchRegex s | |
| in | |
| { snip | conditionalSnippet = { oldConditionalSnippet | condition = newCondition } } | |
| newSnippets = List.map (\(j, s) -> if i == j then f s else s) snippets | |
| in | |
| { model | snippets = newSnippets } | |
| changeGlobalFooter : String -> Model -> Model | |
| changeGlobalFooter newFooter model = | |
| let | |
| newPageState = | |
| case model.pageState of | |
| Nothing -> Nothing | |
| Just state -> let | |
| oldSettings = state.analytic_settings | |
| oldCjs = state.analytic_settings.custom_js_snippets | |
| in | |
| Just <| { state | | |
| analytic_settings = | |
| { oldSettings | | |
| custom_js_snippets = | |
| { oldCjs | | |
| common_footer = Just newFooter | |
| } | |
| } | |
| } | |
| in | |
| { model | pageState = newPageState } | |
| changeGlobalHeader : String -> Model -> Model | |
| changeGlobalHeader newHeader model = | |
| let | |
| newPageState = | |
| case model.pageState of | |
| Nothing -> Nothing | |
| Just state -> let | |
| oldSettings = state.analytic_settings | |
| oldCjs = state.analytic_settings.custom_js_snippets | |
| in | |
| Just <| { state | | |
| analytic_settings = | |
| { oldSettings | | |
| custom_js_snippets = | |
| { oldCjs | | |
| common_header = Just newHeader | |
| } | |
| } | |
| } | |
| in | |
| { model | pageState = newPageState } | |
| changeSnippet : Int -> String -> Model -> Model | |
| changeSnippet j str model = | |
| let | |
| snippets = Array.toIndexedList <| Array.fromList model.snippets | |
| f (i, s) = if i /= j | |
| then s | |
| else let old = s.conditionalSnippet | |
| in {s | conditionalSnippet = { old | snippet = Just str } } | |
| newSnippets = List.map f snippets | |
| in | |
| { model | snippets = newSnippets } | |
| changeHF : Int -> HeaderFooter -> Model -> Model | |
| changeHF j hf model = | |
| let | |
| snippets = Array.toIndexedList <| Array.fromList model.snippets | |
| newSnippets = List.map (\(i, s) -> if i == j then {s | headerFooter = hf} else s) snippets | |
| in | |
| { model | snippets = newSnippets } | |
| removeSnippet : Int -> Model -> Model | |
| removeSnippet j model = | |
| let | |
| snippets = Array.toIndexedList <| Array.fromList model.snippets | |
| newSnippets = List.map Tuple.second <| List.filter (\(i, s) -> i /= j) snippets | |
| in | |
| { model | snippets = newSnippets } | |
| populateSnippets : AnalyticPageState -> List ConvenientSnippet | |
| populateSnippets state = | |
| let | |
| headers = state.analytic_settings.custom_js_snippets.conditional_headers | |
| footers = state.analytic_settings.custom_js_snippets.conditional_footers | |
| f = (\header -> ConvenientSnippet Header header) | |
| g = (\footer -> ConvenientSnippet Footer footer) | |
| in | |
| List.map f headers ++ List.map g footers | |
| populateCjsSnippets : List ConvenientSnippet -> AnalyticPageState -> AnalyticPageState | |
| populateCjsSnippets snippets state = | |
| let | |
| headers = List.map .conditionalSnippet <| List.filter (\snip -> snip.headerFooter == Header) snippets | |
| footers = List.map .conditionalSnippet <| List.filter (\snip -> snip.headerFooter == Footer) snippets | |
| oldSettings = state.analytic_settings | |
| oldSnippets = state.analytic_settings.custom_js_snippets | |
| in | |
| { state | analytic_settings = { | |
| oldSettings | custom_js_snippets = { | |
| oldSnippets | conditional_headers = headers, | |
| conditional_footers = footers | |
| } | |
| } | |
| } | |
| getState : Cmd Msg | |
| getState = | |
| let | |
| url = "/lambda/plugins/analytics/admin/" | |
| request = Http.post url Http.emptyBody jsonDecAnalyticPageState | |
| in | |
| Http.send UpdatePageState request | |
| makeMultiPart : Model -> Http.Body | |
| makeMultiPart model = | |
| let | |
| newState = Maybe.map (populateCjsSnippets model.snippets) model.pageState | |
| in | |
| case newState of | |
| Nothing -> Http.emptyBody | |
| Just state -> Http.multipartBody <| | |
| [ Http.stringPart "snippet_data" (Json.Encode.encode 0 <| jsonEncCustomJsSnippets state.analytic_settings.custom_js_snippets)] | |
| ++ (List.map (\file -> FileReader.filePart file.name file) model.files) | |
| save : Model -> Cmd Msg | |
| save model = | |
| let | |
| url = "/lambda/plugins/analytics/admin/upload/" | |
| request = Http.post url (makeMultiPart model) Json.Decode.bool | |
| in | |
| Http.send (Reload "/lambda/plugins/analytics/admin/") request | |
| subscriptions : Model -> Sub Msg | |
| subscriptions model = Sub.none | |
| -- tells if there is a tracking id present | |
| isIntegrated : Model -> Bool | |
| isIntegrated model = | |
| case model.pageState of | |
| Nothing -> False | |
| Just state -> case state.analytic_settings.google_settings.tracking_id of | |
| Nothing -> False | |
| Just _ -> True | |
| -- ========= | |
| -- UI DESIGN | |
| -- ========= | |
| -- Only comments can help you here | |
| -- Google and facebook stuff | |
| googleknowsallaboutyou : Model -> Html Msg | |
| googleknowsallaboutyou model = | |
| Card.config [ Card.light ] | |
| |> Card.footer [] | |
| [ (conditionallyRender model) | |
| , text " or" | |
| , ( | |
| if isIntegrated model | |
| then | |
| Button.button | |
| [ Button.roleLink, Button.onClick (Reload "#/setup" (Ok True)) ] | |
| [ text "Change/Remove Integration" ] | |
| else | |
| Button.button | |
| [ Button.roleLink, Button.onClick (Reload "#/manual" (Ok True)) ] | |
| [ text "Add tracking ID Manually" ] | |
| ) | |
| ] | |
| |> conditionallyRenderGAData model | |
| |> Card.view | |
| conditionallyRenderGAData model = | |
| let | |
| tracking_id = model.pageState |> Maybe.andThen (.analytic_settings >> .google_settings >> .tracking_id) | |
| website_name = model.pageState |> Maybe.andThen (.analytic_settings >> .google_settings >> .website_name) | |
| website_url = model.pageState |> Maybe.andThen (.analytic_settings >> .google_settings >> .website_url) | |
| in | |
| case (tracking_id, website_name, website_url) of | |
| (Just tid, Just wname, Just wurl) -> | |
| Card.block [] | |
| [ Block.titleH4 [] [ text "Google Analytics" ] | |
| , Block.text [] [ text wname ] | |
| , Block.text [] [ royalchallenge wurl ] | |
| , Block.text [] [ text tid ] | |
| ] | |
| _ -> | |
| Card.block [] | |
| [ Block.titleH4 [] [ text "Google Analytics" ] | |
| , Block.text [] [ text "Connect your Google Account to quickly link your website to Google Analytics. Alternatively, you can add your tracking ID manually, or directly paste the code in 'Add code to site' block below" ] | |
| ] | |
| markzuckerbergiswatchingyou : Html Msg | |
| markzuckerbergiswatchingyou = | |
| Card.config [ Card.light ] | |
| |> Card.footer [] | |
| [ Button.button [ Button.primary ] [ text "Connect Facebook Account" ] | |
| , text " or" | |
| , Button.button [ Button.roleLink ] [ text "Add tracking ID manually" ] | |
| ] | |
| |> Card.block [ Block.light ] | |
| [ Block.titleH4 [] [ text "Facebook Pixel" ] | |
| , Block.text [] [ text "Connect your Facebook Account to quickly link your website to Facebook Pixel. Alternatively, you can visit this link to create a pixel and paste the pixel code in 'Add code to site' block below" ] | |
| ] | |
| |> Card.view | |
| -- Things that go everywhere? | |
| globalheaderandfootersection : Model -> Html Msg | |
| globalheaderandfootersection model = | |
| iwantacontainerwithpaddingplease | |
| [ Grid.simpleRow | |
| [ Grid.col [] | |
| [ h4 [] [text "Add code to site"] | |
| ] | |
| ] | |
| , Grid.simpleRow | |
| [ Grid.col [] | |
| [ p [] [royalchallenge "Header", text " (This code will be added in the header of every page of your website)"] | |
| , pre [] [uglify ChangeGlobalHeader (model.pageState |> Maybe.andThen (.analytic_settings >> .custom_js_snippets >> .common_header))] | |
| ] | |
| ] | |
| , Grid.simpleRow | |
| [ Grid.col [] | |
| [ p [] [royalchallenge "Footer", text " (This code will be added in the footer of every page of your website)"] | |
| , pre [] [uglify ChangeGlobalFooter ( model.pageState |> Maybe.andThen (.analytic_settings >> .custom_js_snippets >> .common_footer) )] | |
| ] | |
| ] | |
| ] | |
| -- How much more flexibility do you want? | |
| customsnippetsection : Model -> Html Msg | |
| customsnippetsection model = | |
| if model.propro then | |
| iwantacontainerwithpaddingplease | |
| [ Grid.simpleRow | |
| [ Grid.col [] | |
| [ p [] [royalchallenge "Set Rules", text " (To add code on specific places, you can setup rules with respect to the paths of different pages on your website)"] | |
| ] | |
| ] | |
| , case (List.isEmpty model.snippets) of | |
| True -> div [] [] | |
| False -> div [] (makeSnippets model) | |
| , Grid.simpleRow | |
| [ Grid.col [ Col.textAlign Text.alignMdCenter ] | |
| [ Button.button | |
| [ Button.info | |
| , Button.onClick AddSnippet | |
| , Button.attrs [ class "round-button" ] | |
| ] [ text "+" ] | |
| ] | |
| ] | |
| , Button.button | |
| [ Button.roleLink | |
| , Button.onClick ToggleProNess | |
| ] | |
| [ text "Hide Advanced Options" ] | |
| ] | |
| else | |
| iwantacontainerwithpaddingplease | |
| [ Button.button | |
| [ Button.roleLink | |
| , Button.onClick ToggleProNess | |
| ] | |
| [ text "Show Advanced Options" ] | |
| ] | |
| makeSnippets : Model -> List (Html Msg) | |
| makeSnippets model = | |
| let | |
| snips = Array.toIndexedList <| Array.fromList model.snippets | |
| f (i, snip) = customsnippet i snip | |
| in | |
| List.map f snips | |
| customsnippet : Int -> ConvenientSnippet -> Html Msg | |
| customsnippet i convsnip = | |
| let | |
| condsnippet = convsnip.conditionalSnippet | |
| hf = convsnip.headerFooter | |
| selectifmatches cond1 = | |
| case (cond1, condsnippet.condition) of | |
| (UMStartsWith _, UMStartsWith _) -> True | |
| (UMEndsWith _, UMEndsWith _) -> True | |
| (UMDoesNotStartWith _, UMDoesNotStartWith _) -> True | |
| (UMDoesNotEndWith _, UMDoesNotEndWith _) -> True | |
| (UMContains _, UMContains _) -> True | |
| (UMDoesNotContain _, UMDoesNotContain _) -> True | |
| (UMMatchesRegex _, UMMatchesRegex _) -> True | |
| (UMDoesNotMatchRegex _, UMDoesNotMatchRegex _) -> True | |
| _ -> False | |
| in | |
| iwantacontainerwithlittlepaddingplease | |
| [ Grid.simpleRow | |
| [ Grid.col [] | |
| [ Card.config [ Card.light ] | |
| |> Card.block [] | |
| [ Block.custom | |
| <| Form.formInline [] | |
| [ text "If the path" | |
| , Select.select | |
| [ Select.onChange (ChangeConditionKind i) | |
| , Select.attrs [ class "extra-margin" ] | |
| ] | |
| [ Select.item | |
| [ value "UMStartsWith", selected (selectifmatches (UMStartsWith ""))] | |
| [ text "starts with" ] | |
| , Select.item | |
| [ value "UMDoesNotStartWith", selected (selectifmatches (UMDoesNotStartWith "")) ] | |
| [ text "doesn't start with" ] | |
| , Select.item | |
| [ value "UMEndsWith", selected (selectifmatches (UMEndsWith "")) ] | |
| [ text "ends with" ] | |
| , Select.item | |
| [ value "UMDoesNotEndWith", selected (selectifmatches (UMDoesNotEndWith "")) ] | |
| [ text "doesn't end with" ] | |
| , Select.item | |
| [ value "UMContains", selected (selectifmatches (UMContains "")) ] | |
| [ text "contains" ] | |
| , Select.item | |
| [ value "UMDoesNotContain", selected (selectifmatches (UMDoesNotContain "")) ] | |
| [ text "doesn't contain" ] | |
| , Select.item | |
| [ value "UMMatchesRegex", selected (selectifmatches (UMMatchesRegex "")) ] | |
| [ text "matches regex" ] | |
| , Select.item | |
| [ value "UMDoesNotMatchRegex", selected (selectifmatches (UMDoesNotMatchRegex "")) ] | |
| [ text "doesn't matches regex" ] | |
| ] | |
| , Input.text | |
| [ Input.onInput (ChangeConditionString i) | |
| , Input.placeholder "e.g. /tours" | |
| , Input.defaultValue (extractString condsnippet.condition) | |
| , Input.attrs [ class "extra-margin" ] | |
| ] | |
| , text "add the following code to the" | |
| , Select.select | |
| [ Select.onChange (ChangeHF i << (\x -> if x == "Header" then Header else Footer)) | |
| , Select.attrs [ class "extra-margin" ] | |
| ] | |
| [ Select.item | |
| [ value "Header" | |
| , selected ((==) Header hf) | |
| ] | |
| [ text "header"] | |
| , Select.item | |
| [ value "Footer" | |
| , selected ((==) Footer hf) | |
| ] | |
| [ text "footer"] | |
| ] | |
| , text "of each page" | |
| ] | |
| , Block.text [] [ royalchallenge "Add Code" ] | |
| , Block.custom <| uglify (ChangeSnippet i) condsnippet.snippet | |
| ] | |
| |> Card.view | |
| ] | |
| , Grid.col [ Col.md1 ] | |
| [ Button.button | |
| [ Button.outlineDanger | |
| , Button.attrs [ class "round-button" ] | |
| , Button.onClick (RemoveSnippet i) | |
| ] | |
| [ text "x" ] | |
| ] | |
| ] | |
| ] | |
| -- Someone's trash is someone's treasure | |
| uglify : (String -> Msg) -> Snippet -> Html Msg | |
| uglify action snippet = | |
| let | |
| extractSnippet = Maybe.withDefault defaultSnippetText snippet | |
| -- action = | |
| -- case j of | |
| -- Maybe i -> (ChangeSnippet i) | |
| -- Nothing -> | |
| -- case hf of | |
| -- Header -> ChangeGlobalHeader | |
| -- Footer -> ChangeGlobalFooter | |
| in | |
| div [] | |
| [ Ace.toHtml | |
| [ Ace.onSourceChange action | |
| , Ace.value extractSnippet | |
| , Ace.mode "javascript" | |
| , Ace.theme "textmate" | |
| , Ace.enableBasicAutocompletion True | |
| , Ace.enableLiveAutocompletion True | |
| , Ace.enableSnippets True | |
| , Ace.tabSize 2 | |
| , Ace.useSoftTabs False | |
| , Ace.extensions [ "language_tools" ] | |
| ] | |
| [] | |
| ] | |
| -- I mean, literally! | |
| fillupmystorage : Model -> Html Msg | |
| fillupmystorage model = | |
| let | |
| domain = .domain_name <| Maybe.withDefault emptyAnalyticPageState model.pageState | |
| filename = "/" ++ (Maybe.withDefault "" <| Maybe.map .name <| List.head model.files) | |
| in | |
| iwantacontainerwithpaddingplease | |
| [ Grid.simpleRow | |
| [ Grid.col [] | |
| [ h4 [] [text "Add files to root directory"] | |
| ] | |
| ] | |
| , Grid.simpleRow | |
| [ Grid.col [ Col.md6 ] | |
| [ p [] [ royalchallenge "Upload files"] | |
| , input [ type_ "file", FileReader.onFileChange AddFiles ] [] | |
| ] | |
| , Grid.col [ Col.md6 ] | |
| [ p [] [ royalchallenge "File path"] | |
| , Input.text | |
| [ Input.defaultValue (domain ++ filename) | |
| , Input.disabled True | |
| ] | |
| ] | |
| ] | |
| ] | |
| -- Convince me that it isn't garbage and I shall change the function name | |
| mygarbage : Model -> Html Msg | |
| mygarbage model = | |
| let | |
| xs = (Maybe.withDefault [] <| Maybe.map (.analytic_settings >> .file_names) model.pageState) | |
| domain = .domain_name <| Maybe.withDefault emptyAnalyticPageState model.pageState | |
| show file = | |
| ListGroup.li | |
| [ ListGroup.light ] | |
| [ a [ href ("//" ++ file ) ] [ text file ] ] | |
| -- show file = | |
| -- Grid.simpleRow | |
| -- [ Grid.col [ Col.md11 ] | |
| -- [ ListGroup.ul | |
| -- [ ListGroup.li | |
| -- [ ListGroup.light ] | |
| -- [ a [ href ("//" ++ file ) ] [ text file ] ] | |
| -- ] | |
| -- ] | |
| -- , Grid.col [ Col.md1, Col.middleMd ] | |
| -- [ Button.button [ Button.attrs [ class "roundButton" ], Button.danger, Button.small ] [ text "x" ] | |
| -- ] | |
| -- ] | |
| in | |
| iwantacontainerwithpaddingplease | |
| [ Grid.simpleRow | |
| [ Grid.col [] | |
| [ h4 [] [text "Uploaded files"] | |
| , case (List.isEmpty xs) of | |
| True -> text "No files have been uploaded yet" | |
| False -> ListGroup.ul | |
| <| List.map (\x -> show <| domain ++ x) xs | |
| ] | |
| ] | |
| ] | |
| -- Go, save the world instead. | |
| destroy : Html Msg | |
| destroy = | |
| iwantacontainerwithpaddingplease | |
| [ Grid.simpleRow | |
| [ Grid.col [] | |
| [ Button.button [ Button.primary, Button.onClick Save ] [ text "Save" ] | |
| ] | |
| ] | |
| ] | |
| -- Debate? | |
| privacytheives : Model -> Html Msg | |
| privacytheives model = | |
| iwantacontainerwithpaddingplease | |
| [ Grid.simpleRow | |
| [ Grid.col [] [googleknowsallaboutyou model] | |
| , Grid.col [] [markzuckerbergiswatchingyou] | |
| ] | |
| ] | |
| -- You have to agree to this | |
| thisisgoingtobethemostawesomeanalyticspagever : Model -> List (Html Msg) | |
| thisisgoingtobethemostawesomeanalyticspagever model = | |
| [ privacytheives model | |
| , letusdrawalinenow | |
| , globalheaderandfootersection model | |
| , letusdrawalinenow | |
| , customsnippetsection model | |
| , letusdrawalinenow | |
| , fillupmystorage model | |
| , letusdrawalinenow | |
| , mygarbage model | |
| , letusdrawalinenow | |
| , destroy | |
| ] | |
| conditionallyRender model = | |
| case model.pageState of | |
| Nothing -> | |
| Button.button [ Button.success, Button.disabled True ] [ text "Connect Google Account" ] | |
| Just state -> | |
| case state.google_integration_state of | |
| Integrated -> | |
| case state.analytic_settings.google_settings.tracking_id of | |
| Nothing -> | |
| Button.button | |
| [ Button.success, Button.onClick (Reload "#/setup" (Ok True)) ] | |
| [ text "Connect Google Account" ] | |
| Just _ -> | |
| Button.button | |
| [ Button.success, Button.onClick (Reload "https://analytics.google.com" (Ok True)) ] | |
| [ text "View Analytics Dashboard" ] | |
| NotIntegrated -> | |
| case state.consent_flow_link of | |
| Just url -> | |
| Button.button | |
| [ Button.success, Button.onClick (Reload url (Ok True)) ] | |
| [ text "Connect Google Account" ] | |
| Nothing -> | |
| Button.button | |
| [ Button.success, Button.disabled True ] | |
| [ text "Connect Google Account" ] | |
| -- Helper UI functions | |
| -- Saying please always helps | |
| iwantacontainerwithpaddingplease : List (Html Msg) -> Html Msg | |
| iwantacontainerwithpaddingplease = Grid.container [ style [("padding", "25px 0 10px")] ] | |
| iwantacontainerwithlittlepaddingplease : List (Html Msg) -> Html Msg | |
| iwantacontainerwithlittlepaddingplease = Grid.container [ style [("padding", "12px 0 8px")] ] | |
| -- Make a "bold" move | |
| royalchallenge : String -> Html Msg | |
| royalchallenge str = strong [] [text str] | |
| -- Blank lines are all I want | |
| letusdrawalinenow : Html Msg | |
| letusdrawalinenow = iwantacontainerwithpaddingplease [ hr [] [] ] | |
| -- Otherwise they won't know what to do | |
| defaultSnippetText : String | |
| defaultSnippetText = """function sayhello() { | |
| console.log(\"Hello, World!\"); | |
| }""" | |
| defaultSnippet : ConvenientSnippet | |
| defaultSnippet = ConvenientSnippet Header { condition = UMStartsWith "Hello", snippet = Just defaultSnippetText } | |
| emptyAnalyticPageState : AnalyticPageState | |
| emptyAnalyticPageState = | |
| { domain_name = "Domain Name" | |
| , consent_flow_link = Nothing | |
| , google_integration_state = NotIntegrated | |
| , analytic_settings = emptyAnalyticSettings | |
| } | |
| emptyAnalyticSettings : AnalyticSettings | |
| emptyAnalyticSettings = | |
| { google_settings = emptyGoogleSettings | |
| , custom_js_snippets = emptyCustomJsSnippet | |
| , file_names = [] | |
| } | |
| emptyGoogleSettings : GoogleSettings | |
| emptyGoogleSettings = | |
| { ecommerce_tracking = False | |
| , tracking_id = Nothing | |
| , website_name = Nothing | |
| , website_url = Nothing | |
| } | |
| emptyCustomJsSnippet : CustomJsSnippets | |
| emptyCustomJsSnippet = | |
| { common_header = Nothing | |
| , common_footer = Nothing | |
| , conditional_headers = [] | |
| , conditional_footers = [] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment