module IHP.IDE.Data.View.Layout ( customQuery , tableHead , renderRows , sqlValueToText , renderId , isBoolField , isSqlFunction , isSqlFunction_ , fillField , getColDefaultValue , renderRowValue , renderDefaultWithoutType , isBooleanParam , headerNav ) where import IHP.ViewPrelude import IHP.IDE.ToolServer.Types import IHP.IDE.ToolServer.Routes () import qualified Data.Text as Text import IHP.IDE.ToolServer.Helper.View customQuery :: Text -> Html customQuery :: Text -> Html customQuery Text input = [hsx|<div class="p-2 rounded mt-2" style="background-color: #002B36;"><div id="queryInput" style="height:16px">{input}</div></div>|] tableHead :: [[DynamicField]] -> Text -> Html tableHead :: [[DynamicField]] -> Text -> Html tableHead [[DynamicField]] rows Text tableName = [hsx| <thead> <tr> {forEach (columnNames rows) renderColumnHead} <th> <div class="d-flex"> <a href={NewRowAction tableName} class="btn btn-link btn-add" data-toggle="tooltip" data-placement="bottom" title={"Add " <> tableNameToModelName tableName} >{addIcon}</a> </div> </th> </tr> </thead> |] where columnNames :: [[a]] -> [b] columnNames [[a]] rows = (a -> b) -> [a] -> [b] forall a b. (a -> b) -> [a] -> [b] map (.fieldName) ([a] -> Maybe [a] -> [a] forall a. a -> Maybe a -> a fromMaybe [] ([[a]] -> Maybe [a] forall a. [a] -> Maybe a head [[a]] rows)) renderColumnHead :: a -> Html renderColumnHead a name = [hsx|<th>{name}</th>|] renderRows :: [[DynamicField]] -> Html -> Text -> Html renderRows :: [[DynamicField]] -> Html -> Text -> Html renderRows [[DynamicField]] rows Html body Text tableName = [hsx| <table class="table table-sm table-hover data-rows-table"> {tableHead rows tableName} {body} </table> |] sqlValueToText :: Maybe ByteString -> Text sqlValueToText :: Maybe ByteString -> Text sqlValueToText (Just ByteString value) = ByteString -> Text forall a b. ConvertibleStrings a b => a -> b cs ByteString value sqlValueToText Maybe ByteString Nothing = Text "NULL" renderId :: a -> [Char] renderId a id = Int -> [Char] -> [Char] forall a. Int -> [a] -> [a] take Int 4 (a -> [Char] forall a b. ConvertibleStrings a b => a -> b cs a id) [Char] -> [Char] -> [Char] forall a. Semigroup a => a -> a -> a <> [Char] ".." [Char] -> [Char] -> [Char] forall a. Semigroup a => a -> a -> a <> [Char] -> [Char] forall a. [a] -> [a] reverse (Int -> [Char] -> [Char] forall a. Int -> [a] -> [a] take Int 4 ([Char] -> [Char] forall a. [a] -> [a] reverse (a -> [Char] forall a b. ConvertibleStrings a b => a -> b cs a id))) isBoolField :: a -> t r -> Bool isBoolField a fieldName t r tableCols = case ((r -> Bool) -> t r -> Maybe r forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a find (\r c -> r c.columnName a -> a -> Bool forall a. Eq a => a -> a -> Bool == (a -> a forall a b. ConvertibleStrings a b => a -> b cs a fieldName)) t r tableCols) of Just r columnDef -> (r columnDef.columnType) a -> a -> Bool forall a. Eq a => a -> a -> Bool == a "boolean" Maybe r Nothing -> Bool False isSqlFunction :: Text -> Bool isSqlFunction :: Text -> Bool isSqlFunction Text text = Text text Text -> [Text] -> Bool forall a. Eq a => a -> [a] -> Bool forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool `elem` [ Text "uuid_generate_v4()" , Text "NOW()" , Text "NULL"] isSqlFunction_ :: ByteString -> Bool isSqlFunction_ :: ByteString -> Bool isSqlFunction_ ByteString text = ByteString text ByteString -> [ByteString] -> Bool forall a. Eq a => a -> [a] -> Bool forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool `elem` [ ByteString "uuid_generate_v4()" , ByteString "NOW()" , ByteString "NULL"] fillField :: r -> a -> a -> a fillField r col a value a isBoolField = a "fillField('" a -> a -> a forall a. Semigroup a => a -> a -> a <> r col.columnName a -> a -> a forall a. Semigroup a => a -> a -> a <> a "', '" a -> a -> a forall a. Semigroup a => a -> a -> a <> a value a -> a -> a forall a. Semigroup a => a -> a -> a <> a "'," a -> a -> a forall a. Semigroup a => a -> a -> a <> a isBoolField a -> a -> a forall a. Semigroup a => a -> a -> a <> a ");" getColDefaultValue :: ColumnDefinition -> Text getColDefaultValue :: ColumnDefinition -> Text getColDefaultValue ColumnDefinition { Maybe Text columnDefault :: Maybe Text $sel:columnDefault:ColumnDefinition :: ColumnDefinition -> Maybe Text columnDefault, Bool isNullable :: Bool $sel:isNullable:ColumnDefinition :: ColumnDefinition -> Bool isNullable } = case Maybe Text columnDefault of Just Text value -> Text value Maybe Text Nothing -> if Bool isNullable then Text "NULL" else Text "" renderRowValue :: Maybe ByteString -> Text renderRowValue :: Maybe ByteString -> Text renderRowValue (Just ByteString value) = Text "'" Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> ByteString -> Text forall a b. ConvertibleStrings a b => a -> b cs ByteString value Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> Text "'" renderRowValue Maybe ByteString Nothing = Text "NULL" renderDefaultWithoutType :: Text -> Text renderDefaultWithoutType :: Text -> Text renderDefaultWithoutType Text "" = Text "" renderDefaultWithoutType Text input = case [Text] -> Int forall a. [a] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length (HasCallStack => Text -> Text -> [Text] Text -> Text -> [Text] Text.splitOn Text "'" Text input) of Int 3 -> (HasCallStack => Text -> Text -> [Text] Text -> Text -> [Text] Text.splitOn Text "'" Text input) [Text] -> Int -> Text forall a. HasCallStack => [a] -> Int -> a !! Int 1 Int _ -> Text input isBooleanParam :: Bool -> ColumnDefinition -> Html isBooleanParam :: Bool -> ColumnDefinition -> Html isBooleanParam Bool isBool ColumnDefinition def = [hsx| <input type="hidden" name={def.columnName <> "-isBoolean"} value={inputValue isBool} /> |] headerNav :: Html = [hsx| <div class="view-selector"> <div class="container-fluid"> <a href={ShowDatabaseAction} class={classes [("active", databaseActive)]}> Database </a> <a href={NewQueryAction} class={classes [("active", sqlActive)]}> SQL </a> </div> </div> |] where databaseActive :: Bool databaseActive :: Bool databaseActive = forall controller. (?context::ControllerContext, Typeable controller) => Bool forall {k} (controller :: k). (?context::ControllerContext, Typeable controller) => Bool isActiveController @DataController Bool -> Bool -> Bool && Bool -> Bool not Bool sqlActive sqlActive :: Bool sqlActive :: Bool sqlActive = DataController -> Bool forall controller. (?context::ControllerContext, PathString controller) => controller -> Bool isActivePath DataController NewQueryAction Bool -> Bool -> Bool || DataController -> Bool forall controller. (?context::ControllerContext, PathString controller) => controller -> Bool isActivePath DataController QueryAction