From 332e83a111fae491f8240e2d30c5c97f7b1baabe Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 4 Jun 2019 10:08:57 +0200 Subject: [PATCH 1/2] Fix handling of URL-encoded jsonFields See #392 --- src/Handler/Utils/Form.hs | 2 +- src/Handler/Utils/Table/Pagination.hs | 8 ++++++-- src/Utils/Form.hs | 27 +++++++++++++++++---------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/Handler/Utils/Form.hs b/src/Handler/Utils/Form.hs index 0b661e87e..0b6850b24 100644 --- a/src/Handler/Utils/Form.hs +++ b/src/Handler/Utils/Form.hs @@ -689,7 +689,7 @@ jsonField hide = Field{..} inputType | hide = "hidden" | otherwise = "text" - fieldParse [v] [] = return . bimap (SomeMessage . MsgJSONFieldDecodeFailure) Just . eitherDecodeStrict' $ encodeUtf8 v + fieldParse [encodeUtf8 -> v] [] = return . bimap (SomeMessage . MsgJSONFieldDecodeFailure) Just $ eitherDecodeStrict' v <|> eitherDecodeStrict' (urlDecode True v) fieldParse [] [] = return $ Right Nothing fieldParse _ _ = return . Left $ SomeMessage MsgValueRequired fieldView theId name attrs val isReq = liftWidgetT [whamlet| diff --git a/src/Handler/Utils/Table/Pagination.hs b/src/Handler/Utils/Table/Pagination.hs index 52c1b3ec8..e87d4a405 100644 --- a/src/Handler/Utils/Table/Pagination.hs +++ b/src/Handler/Utils/Table/Pagination.hs @@ -641,8 +641,12 @@ dbTable PSValidator{..} dbtable@DBTable{ dbtIdent = dbtIdent'@(toPathPiece -> db , fieldEnctype = UrlEncoded } - piPrevious <- lift . runInputMaybe $ ireq (jsonField True) (wIdent "pagination") - let piPreviousRes = maybe FormMissing FormSuccess piPrevious + piPreviousPost <- lift . runInputPost $ iopt (jsonField True) (wIdent "pagination") + piPreviousGet <- lift . runInputGet $ iopt (jsonField True) (wIdent "pagination") + let + piPreviousRes = maybe FormMissing FormSuccess $ piPreviousPost <|> piPreviousGet + $logDebugS "dbTable" [st|#{wIdent "pagination"}: #{tshow piPreviousRes}|] + previousKeys <- throwExceptT . runMaybeT $ encodedSecretBoxOpen =<< MaybeT (lift . lookupPostParam $ wIdent "previous") piInput <- lift . runInputGetResult $ PaginationInput diff --git a/src/Utils/Form.hs b/src/Utils/Form.hs index 2c04192ec..629e82de8 100644 --- a/src/Utils/Form.hs +++ b/src/Utils/Form.hs @@ -621,18 +621,25 @@ formResult' (FormFailure _) = Nothing formResult' (FormSuccess x) = Just x runInputGetMaybe, runInputPostMaybe, runInputMaybe :: MonadHandler m => FormInput m a -> m (Maybe a) -runInputGetMaybe form = do - res <- runInputGetResult form - return $ case res of - FormSuccess suc -> Just suc - _other -> Nothing -runInputPostMaybe form = do - res <- runInputPostResult form - return $ case res of - FormSuccess suc -> Just suc - _other -> Nothing +runInputGetMaybe = fmap formResult' . runInputGetResult +runInputPostMaybe = fmap formResult' . runInputPostResult runInputMaybe form = runMaybeT $ MaybeT (runInputPostMaybe form) <|> MaybeT (runInputGetMaybe form) +runInputResult :: MonadHandler m => FormInput m a -> m (FormResult a) +runInputResult form = do + postRes <- runInputPostResult form + getRes <- runInputGetResult form + return $ case (postRes, getRes) of + (FormSuccess a, _) -> FormSuccess a + (_, FormSuccess b) -> FormSuccess b + (postRes', _) -> postRes' + +runInput :: (MonadHandler m, RenderMessage (HandlerSite m) FormMessage) => FormInput m a -> m a +runInput = runInputResult >=> \case + FormFailure errs -> invalidArgs errs + FormMissing -> invalidArgsI [MsgValueRequired] + FormSuccess a -> return a + hoistAForm :: HandlerSite m ~ HandlerSite n => (forall a. m a -> n a) -> AForm m b -> AForm n b hoistAForm f (AForm g) = AForm (\x y z ->f $ g x y z) From 70b0e536cf1b345f839eb304c14d6aa28710133b Mon Sep 17 00:00:00 2001 From: Felix Hamann Date: Wed, 5 Jun 2019 22:17:45 +0200 Subject: [PATCH 2/2] ignore pending requests for async table filters if new input exists closes #325 --- frontend/src/utils/async-table/async-table.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/frontend/src/utils/async-table/async-table.js b/frontend/src/utils/async-table/async-table.js index dd6e532b9..416ebd34c 100644 --- a/frontend/src/utils/async-table/async-table.js +++ b/frontend/src/utils/async-table/async-table.js @@ -38,6 +38,7 @@ export class AsyncTable { change: [], select: [], }; + _ignoreRequest = false; constructor(element, app) { if (!element) { @@ -174,6 +175,10 @@ export class AsyncTable { } }, INPUT_DEBOUNCE); input.addEventListener('input', debouncedInput); + input.addEventListener('input', () => { + // set flag to ignore any currently pending requests (not debounced) + this._ignoreRequest = true; + }); }); this._tableFilterInputs.input.forEach((input) => { @@ -183,6 +188,10 @@ export class AsyncTable { } }, INPUT_DEBOUNCE); input.addEventListener('input', debouncedInput); + input.addEventListener('input', () => { + // set flag to ignore any currently pending requests (not debounced) + this._ignoreRequest = true; + }); }); this._tableFilterInputs.change.forEach((input) => { @@ -224,6 +233,7 @@ export class AsyncTable { } }; } + this._ignoreRequest = false; this._updateTableFrom(url, callback); } @@ -340,8 +350,13 @@ export class AsyncTable { url: url, headers: headers, }).then( - (response) => this._app.htmlHelpers.parseResponse(response) + (response) => this._app.htmlHelpers.parseResponse(response), ).then((response) => { + // check if request should be ignored + if (this._ignoreRequest) { + return false; + } + setLocalStorageParameter('currentTableUrl', url.href); // reset table this._removeListeners();