module ArrayBased.Update exposing (update) import Array import Array.Extra import ArrayBased.Messages exposing (..) import ArrayBased.Model exposing (..) import InputTable.Update import InputTable.Model exposing (..) import InputTable.Messages exposing (..) import Date import List.Extra import ArrayBased.GetInputTableCommands exposing (..) import Utils import ArrayBased.GetTableData type alias Config = { initialGetUrl : String , postRowsUrl : String , postVisibleColumnsUrl : String , currentPage : Int } update : Config -> Msg -> Model -> ( Model, Cmd Msg ) update config msg model = case msg of Table tableMsg -> let ( newTableState, tableCmd ) = InputTable.Update.update tableMsg model.tableState savingState = case tableMsg of SetCellValue _ _ _ _ _ -> Saving SetSideBarTinyMceValue _ -> Saving SetBoolCellValue _ _ _ _ -> Saving SelectDropdownChild _ _ _ _ _ -> Saving _ -> model.tableState.savingState cmd = getInputTableCommands config tableMsg model newTableState in ( { model | tableState = { newTableState | savingState = savingState } } , Cmd.batch [ cmd, (Cmd.map Table tableCmd) ] ) UpdateDataFromServer (Ok { headers, accordionHeaders, rows, showVisibleColumnsUi, headerIdsToRemoteIds, incompleteText, incompleteColumn, sideBarHeaders, tableAction, sideRows, hasSideTable, sideTableAction, sideTablePreposition, rowIdsToTitles }) -> let tableState = model.tableState newTableState = { tableState | columns = List.map makeColumnHeader headers , accordionColumns = Maybe.map (List.map makeAccordionColumn) accordionHeaders , rows = List.map makeRow rows , sideBarHeaders = Just (List.map makeSidebarHeader (Maybe.withDefault [] (sideBarHeaders))) , tableAction = tableAction , showVisibleColumnsUi = showVisibleColumnsUi , sideRows = sideRows , hasSideTable = hasSideTable , sideTableAction = sideTableAction , sideTablePreposition = sideTablePreposition , rowIdsToTitles = rowIdsToTitles } newIncompleteColumnAndText = case incompleteColumn of Just index -> Just ( index, incompleteText ) Nothing -> Nothing in ( { model | tableState = newTableState , headerIdsToRemoteIds = headerIdsToRemoteIds , incompleteColumnAndText = newIncompleteColumnAndText , isLoadingInitialRows = False } , Cmd.none ) UpdateDataFromServer (Err errorMessage) -> ( { model | isLoadingInitialRows = False }, Cmd.none ) RecievePostNotification (Ok postReply) -> let newTableState = updateTableState model.tableState postReply.updates updateTableState tableState updates = { tableState | rows = List.map (updateRowIfHasId updates) tableState.rows , savingState = Saved } updateRowIfHasId updates row = let update = List.Extra.find (\u -> u.rowId == row.id) updates in case update of Nothing -> row Just update -> { row | data = Array.Extra.update update.columnId (\c -> { c | value = update.value }) row.data } in ( { model | postMessage = postReply.status , tableState = newTableState } , Cmd.none ) RecievePostNotification (Err errorMessage) -> let tableState = model.tableState newTableState = { tableState | savingState = Error } in ( { model | postMessage = "woops", tableState = newTableState }, Cmd.none ) RecieveColumnsPostNotification (Ok _) -> ( model, Cmd.none ) RecieveColumnsPostNotification (Err _) -> ( model, Cmd.none ) RecieveSideTablePostNotification (Ok _) -> let tableState = model.tableState newTableState = { tableState | sideTableIsAssigning = False , rows = uncheck tableState.rows , sideRows = uncheck tableState.sideRows , savingState = Saved } in ( { model | tableState = newTableState } , ArrayBased.GetTableData.fetchDataFromServer config.initialGetUrl ) RecieveSideTablePostNotification (Err errorMessage) -> let tableState = model.tableState newTableState = { tableState | sideTableIsAssigning = False , cannotAssignSideRowsReason = Just "Sorry There was an error assigning the submissions" } in ( { model | tableState = newTableState } , Cmd.none ) uncheck : List { a | checked : Bool } -> List { a | checked : Bool } uncheck = List.map (\x -> { x | checked = False }) makeAccordionColumn : HeaderData -> AccordionColumn RowData makeAccordionColumn headerData = { id = headerData.id , name = headerData.title , hasNumericalValues = headerData.hasNumericalValues , link = Nothing , description = Maybe.withDefault "" headerData.description , get = makeColumnGetter headerData.id } makeColumnHeader : HeaderData -> Column RowData makeColumnHeader headerData = let description = Maybe.withDefault "" headerData.description subType = case headerData.subType of "TEXT_AREA" -> TextColumn (TextColumnProps (makeColumnGetter headerData.id) (makeColumnsSetter headerData.id) "" True ) "TEXT_INPUT" -> TextColumn (TextColumnProps (makeColumnGetter headerData.id) (makeColumnsSetter headerData.id) "" False ) "DROPDOWN_INPUT" -> DropdownColumn (DropdownColumnProps (makeColumnGetter headerData.id) (makeColumnsSetter headerData.id) "" headerData.options ) "MENU_DROPDOWN_INPUT" -> MenuDropdownColumn (MenuDropdownColumnProps (makeColumnGetter headerData.id) (makeColumnsSetter headerData.id) "" headerData.options headerData.displayedTextOptions ) "CHECKBOX_INPUT" -> CheckboxColumn (CheckboxColumnProps (makeBoolColumnGetter headerData.id) (makeBoolColumnSetter headerData.id) Nothing ) "LINK_COLUMN" -> LinkColumn (LinkColumnProps (makeColumnGetter headerData.id) (makeLinkGetter headerData.id) "" ) "SIDEBAR_BUTTON" -> SideBarButtonColumn (SideBarButtonColumnProps (makeColumnGetter headerData.id) (makeColumnsSetter headerData.id) "" ) "DATE_TIME" -> DisplayColumn (DisplayColumnProps (makeDateTimeGetter headerData.id) "" (Just (makeColumnGetter headerData.id))) _ -> DisplayColumn (DisplayColumnProps (makeColumnGetter headerData.id) "" Nothing) in Column headerData.id headerData.title headerData.visible headerData.hasNumericalValues subType description makeSidebarHeader : SideBarHeaderData -> SideBarHeader RowData makeSidebarHeader sideBarHeaderData = let description = Maybe.withDefault "" sideBarHeaderData.description subType = case sideBarHeaderData.subType of "DROPDOWN_INPUT" -> SideBarDropdown (SideBarDropdownColumnProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) (sideBarHeaderData.options) ) "MENU_DROPDOWN_INPUT" -> SideBarMenuDropdown (SideBarMenuDropdownColumnProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) sideBarHeaderData.options sideBarHeaderData.displayedTextOptions ) "CHECKBOX_INPUT" -> SideBarCheckbox (SideBarHeaderBoolProps (makeBoolColumnGetter sideBarHeaderData.id) (makeBoolColumnSetter sideBarHeaderData.id) ) "TEXT_AREA" -> SideBarTextArea (SideBarHeaderStringProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) ) "TEXT_INPUT" -> SideBarTextInput (SideBarHeaderStringProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) ) "MULTI_RADIO_INPUT" -> SideBarMultiRadioInput (SideBarMultiRadioProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) (sideBarHeaderData.options) ) "MULTI_CHECKBOX_INPUT" -> SideBarMultiCheckboxInput (SideBarHeaderMultiCheckboxProps (makeMultiCheckColumnGetter sideBarHeaderData.id) (makeMultiCheckColumnSetter sideBarHeaderData.id) (sideBarHeaderData.options) ) "MCE_INPUT_TYPE1" -> SideBarMceInputType1 (SideBarHeaderStringProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) ) "MCE_INPUT_TYPE2" -> SideBarMceInputType2 (SideBarHeaderStringProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) ) "MCE_INPUT_TYPE3" -> SideBarMceInputType3 (SideBarHeaderStringProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) ) "MCE_INPUT_TYPE4" -> SideBarMceInputType4 (SideBarHeaderStringProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) ) _ -> SideBarTextInput (SideBarHeaderStringProps (makeColumnGetter sideBarHeaderData.id) (makeColumnsSetter sideBarHeaderData.id) ) in SideBarHeader sideBarHeaderData.id sideBarHeaderData.title subType [] sideBarHeaderData.hasNumericalValues (Just description) makeColumnGetter : String -> RowData -> String makeColumnGetter id = Array.get (idToInt id) >> Maybe.map .value >> Maybe.withDefault "N/A" makeLinkGetter : String -> Row RowData -> String makeLinkGetter id = .data >> Array.get (idToInt id) >> Maybe.andThen .link >> Maybe.withDefault "" makeDateTimeGetter : String -> RowData -> String makeDateTimeGetter id = makeColumnGetter id >> Utils.displayTimeStamp makeColumnsSetter : String -> RowData -> String -> RowData makeColumnsSetter id row newValue = Array.Extra.update (idToInt id) (\c -> { c | value = newValue }) row makeBoolColumnGetter : String -> RowData -> Bool makeBoolColumnGetter id = let stringToBool string = {- Not keen on next line but needed to work with our db convention of storing bools from checkboxes as strings -} if string == "True" || string == "true" then True else False in Array.get (idToInt id) >> Maybe.map .value >> Maybe.withDefault "" >> stringToBool makeBoolColumnSetter : String -> RowData -> Bool -> RowData makeBoolColumnSetter id row newValue = Array.Extra.update (idToInt id) (\c -> { c | value = toString newValue }) row --the responses are sent in the payload as a string, each response is separated by the string '*SPLITTER*' --to fix #4645 makeMultiCheckColumnGetter : String -> RowData -> List String makeMultiCheckColumnGetter id = Array.get (idToInt id) >> Maybe.map .value >> Maybe.withDefault "N/A" >> String.split "*SPLITTER*" makeMultiCheckColumnSetter : String -> RowData -> String -> RowData makeMultiCheckColumnSetter id row newValue = Array.Extra.update (idToInt id) (\c -> { c | value = newValue }) row makeRow : ApiRowData -> Row RowData makeRow apiRowData = { id = apiRowData.id , data = apiRowData.cells , checked = False , disabledMsg = Nothing , checkboxDisabledMsg = apiRowData.checkboxDisabledMsg , accordionRows = apiRowData.accordionRows , accordionExpanded = False , rowFocusUrl = apiRowData.rowFocusUrl } idToInt : String -> Int idToInt = String.toInt >> Result.withDefault -1