module IHP.IDE.Data.View.NewRow where import IHP.ViewPrelude import IHP.IDE.ToolServer.Types import IHP.IDE.Data.View.ShowDatabase import IHP.IDE.Data.View.Layout import Data.Maybe import qualified Data.Text as Text data NewRowView = NewRowView { NewRowView -> [Text] tableNames :: [Text] , NewRowView -> Text tableName :: Text , NewRowView -> [[DynamicField]] rows :: [[DynamicField]] , NewRowView -> [ColumnDefinition] tableCols :: [ColumnDefinition] } instance View NewRowView where html :: (?context::ControllerContext, ?view::NewRowView) => NewRowView -> Html html NewRowView { [[DynamicField]] [Text] [ColumnDefinition] Text $sel:tableNames:NewRowView :: NewRowView -> [Text] $sel:tableName:NewRowView :: NewRowView -> Text $sel:rows:NewRowView :: NewRowView -> [[DynamicField]] $sel:tableCols:NewRowView :: NewRowView -> [ColumnDefinition] tableNames :: [Text] tableName :: Text rows :: [[DynamicField]] tableCols :: [ColumnDefinition] .. } = [hsx| <div class="h-100"> {headerNav} <div class="h-100 row no-gutters"> {renderTableSelector tableNames tableName} <div class="col" style="overflow: scroll; max-height: 80vh"> {renderRows rows tableBody tableName} </div> </div> </div> {renderModal modal} |] where tableBody :: Html tableBody = [hsx|<tbody>{forEach rows renderRow}</tbody>|] renderRow :: [DynamicField] -> Html renderRow [DynamicField] fields = [hsx|<tr>{forEach fields (renderField id)}</tr>|] where id :: Text id = (ByteString -> Text forall a b. ConvertibleStrings a b => a -> b cs (ByteString -> Maybe ByteString -> ByteString forall a. a -> Maybe a -> a fromMaybe ByteString "" ((Maybe DynamicField -> DynamicField forall a. HasCallStack => Maybe a -> a fromJust ([DynamicField] -> Maybe DynamicField forall a. [a] -> Maybe a headMay [DynamicField] fields)).fieldValue))) renderField :: Text -> DynamicField -> Html renderField Text id DynamicField { Maybe ByteString ByteString fieldValue :: Maybe ByteString fieldName :: ByteString $sel:fieldValue:DynamicField :: DynamicField -> Maybe ByteString $sel:fieldName:DynamicField :: DynamicField -> ByteString .. } | ByteString fieldName ByteString -> ByteString -> Bool forall a. Eq a => a -> a -> Bool == ByteString "id" = [hsx|<td><span data-fieldname={fieldName}><a class="no-link border rounded p-1" href={EditRowValueAction tableName (cs fieldName) id}>{renderId (sqlValueToText fieldValue)}</a></span></td>|] renderField Text id DynamicField { Maybe ByteString ByteString $sel:fieldValue:DynamicField :: DynamicField -> Maybe ByteString $sel:fieldName:DynamicField :: DynamicField -> ByteString fieldValue :: Maybe ByteString fieldName :: ByteString .. } | ByteString -> [ColumnDefinition] -> Bool forall {t :: * -> *} {a1} {a2} {a3} {r}. (Foldable t, ConvertibleStrings a1 a2, Eq a2, Eq a3, HasField "columnName" r a2, HasField "columnType" r a3, IsString a3) => a1 -> t r -> Bool isBoolField ByteString fieldName [ColumnDefinition] tableCols Bool -> Bool -> Bool && Bool -> Bool not (Maybe ByteString -> Bool forall a. Maybe a -> Bool isNothing Maybe ByteString fieldValue) = [hsx|<td><span data-fieldname={fieldName}><input type="checkbox" onclick={onClick tableName fieldName id} checked={sqlValueToText fieldValue == "t"} /></span></td>|] renderField Text id DynamicField { Maybe ByteString ByteString $sel:fieldValue:DynamicField :: DynamicField -> Maybe ByteString $sel:fieldName:DynamicField :: DynamicField -> ByteString fieldValue :: Maybe ByteString fieldName :: ByteString .. } = [hsx|<td><span data-fieldname={fieldName}><a class="no-link" href={EditRowValueAction tableName (cs fieldName) id}>{sqlValueToText fieldValue}</a></span></td>|] modalContent :: Html modalContent = [hsx| <form method="POST" action={CreateRowAction}> <input type="hidden" name="tableName" value={tableName}/> {forEach tableCols renderFormField} {renderFlashMessages} <div class="text-right"> <button type="submit" class="btn btn-primary">Add Row</button> </div> </form> |] modalFooter :: Maybe Html modalFooter = Maybe Html forall a. Monoid a => a mempty modalCloseUrl :: Text modalCloseUrl = DataController -> Text forall controller. HasPath controller => controller -> Text pathTo ShowTableRowsAction { Text tableName :: Text $sel:tableName:ShowDatabaseAction :: Text tableName } modalTitle :: Text modalTitle = Text "Add Row" modal :: Modal modal = Modal { Html modalContent :: Html $sel:modalContent:Modal :: Html modalContent, Maybe Html modalFooter :: Maybe Html $sel:modalFooter:Modal :: Maybe Html modalFooter, Text modalCloseUrl :: Text $sel:modalCloseUrl:Modal :: Text modalCloseUrl, Text modalTitle :: Text $sel:modalTitle:Modal :: Text modalTitle } renderFormField :: ColumnDefinition -> Html renderFormField ColumnDefinition col = [hsx| <div class="form-group"> <label class="row-form">{col.columnName}</label> <span style="float:right;"> <a class="text-muted row-form">{col.columnType}</a> </span> <div class="d-flex"> {renderInputMethod col} </div> </div>|] onClick :: Text -> a -> Text -> Text onClick Text tableName a fieldName Text id = Text "window.location.assign(" Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> Text -> Text forall a. Show a => a -> Text tshow (DataController -> Text forall controller. HasPath controller => controller -> Text pathTo (Text -> Text -> Text -> DataController ToggleBooleanFieldAction Text tableName (a -> Text forall a b. ConvertibleStrings a b => a -> b cs a fieldName) Text id)) Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> Text ")" renderInputMethod :: ColumnDefinition -> Html renderInputMethod :: ColumnDefinition -> (?context::ControllerContext) => Html renderInputMethod ColumnDefinition col | (ColumnDefinition col.columnType) Text -> Text -> Bool forall a. Eq a => a -> a -> Bool == Text "boolean" = [hsx| {isBooleanParam True col} <input id={col.columnName <> "-alt"} type="text" name={col.columnName <> "-inactive"} class="form-control text-monospace text-secondary d-none" /> <div class="form-control" id={col.columnName <> "-boxcontainer"}> <input id={col.columnName <> "-input"} type="checkbox" name={col.columnName} checked={col.columnDefault == Just "true"} /> </div> <input id={col.columnName <> "-hidden"} type="hidden" name={col.columnName} value={inputValue False} /> <div class="input-group-append"> <button class="btn dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button> <div class="dropdown-menu dropdown-menu-right custom-menu menu-for-column shadow backdrop-blur"> <a class="dropdown-item" data-value="DEFAULT" data-issql="True" onclick={fillField col "DEFAULT" "true"}>DEFAULT</a> <a class="dropdown-item" data-value="NULL" data-issql="True" onclick={fillField col "NULL" "true"}>NULL</a> <a class="dropdown-item"> <input id={col.columnName <> "-sqlbox"} type="checkbox" name={col.columnName <> "_"} checked={isSqlFunction (getColDefaultValue col)} class="mr-1" onclick={"sqlModeCheckbox('" <> col.columnName <> "', this, true)"} /> <label class="form-check-label" for={col.columnName <> "-sqlbox"}> Parse as SQL</label> </a> <input type="hidden" name={col.columnName <> "_"} value={inputValue False} /> </div> </div> |] renderInputMethod ColumnDefinition col = [hsx| {isBooleanParam False col} {if isForeignKeyColumn then select else theInput } <button class="btn dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button> <div class="dropdown-menu dropdown-menu-right custom-menu menu-for-column shadow backdrop-blur"> <a class="dropdown-item" data-value="DEFAULT" data-issql="True" onclick={fillField col "DEFAULT" "false"}>DEFAULT</a> <a class="dropdown-item" data-value="NULL" data-issql="True" onclick={fillField col "NULL" "false"}>NULL</a> <a class="dropdown-item"> <input id={col.columnName <> "-sqlbox"} type="checkbox" name={col.columnName <> "_"} checked={isSqlFunction (getColDefaultValue col)} class="mr-1" onclick={"sqlModeCheckbox('" <> col.columnName <> "', this, false)"} /> <label class="form-check-label" for={col.columnName <> "-sqlbox"}> Parse as SQL</label> </a> <input type="hidden" name={col.columnName <> "_"} value={inputValue False} /> </div> |] where isForeignKeyColumn :: Bool isForeignKeyColumn :: Bool isForeignKeyColumn = Text "_id" Text -> Text -> Bool `Text.isSuffixOf` (ColumnDefinition col.columnName) theInput :: Html theInput :: (?context::ControllerContext) => Html theInput = [hsx| <input id={col.columnName <> "-input"} type="text" name={col.columnName} class={classes ["form-control", ("text-monospace", isSqlFunction (getColDefaultValue col)), ("is-foreign-key-column", isForeignKeyColumn)]} value={renderDefaultWithoutType (getColDefaultValue col)} oninput={"stopSqlModeOnInput('" <> col.columnName <> "')"} /> |] select :: Html select :: (?context::ControllerContext) => Html select = [hsx| <select id={col.columnName <> "-input"} name={col.columnName} class={classes ["form-control", ("is-foreign-key-column", isForeignKeyColumn)]} value={renderDefaultWithoutType (getColDefaultValue col)} data-select-url={selectUrl} /> |] selectUrl :: Text selectUrl :: Text selectUrl = DataController -> Text forall controller. HasPath controller => controller -> Text pathTo AutocompleteForeignKeyColumnAction { Text tableName :: Text $sel:tableName:ShowDatabaseAction :: Text tableName, $sel:columnName:ShowDatabaseAction :: Text columnName = ColumnDefinition col.columnName, $sel:term:ShowDatabaseAction :: Maybe Text term = Maybe Text "" }