-
Notifications
You must be signed in to change notification settings - Fork 4
Form rendering
Формочки в UI примерно соответствуют таблицам в БД.
В carma-models на eDSL описаны таблицы вместе с метаинформацией о том как колонки должны превратиться в поля формы в UI. Это же типизированное описание БД используется в некоторых местах для конструирования SQL-запросов.
Например:
data CaseComment = CaseComment
{ ident
:: PK Int CaseComment "Комментарий к кейсу"
, caseId
:: F (IdentI Case) "caseId" "Кейс"
, ctime
:: F UTCTime "ctime" "Дата/время"
, author
:: F (IdentI Usermeta) "author" "Автор"
, comment
:: F Text "comment" "Комментарий"
} deriving Typeable
Тут тип поля, его название в БД и комментарий. Эта информация дальше превращается в JSON-описание того, как поле отображать (view), и передаётся в фронтенд. Фронтенд-код подбирает html-шаблон для каждого поля и отрисовывает его. Для большинства полей достаточно типа данных и русскоязычного названия для того, чтобы сформировать JSON-описание.
Например, вот этот instance DefaultFiledView
превращает F (IdentI Usermeta) "author" "Автор"
в выпадающий справочник пользователей.
instance Typeable tag => DefaultFieldView (Ident Int tag) where
defaultFieldView f = (defFieldView f)
{fv_type = "dictionary"
,fv_meta
= Map.insert "dictionaryName" (Aeson.String $ typeName (undefined :: tag))
$ Map.insert "dictionaryType" "ModelDict"
$ Map.insert "bounded" (Aeson.Bool True)
$ fv_meta $ defFieldView f
}
А вот так F UTCTime "ctime" "Дата/время"
превращается в текстовое поле с проверкой формата даты регулярным выражением:
instance DefaultFieldView UTCTime where
defaultFieldView f = (defFieldView f)
{ fv_type = "UTCTime"
, fv_meta
= Map.insert "regexp" (Aeson.String regexpDateTime)
$ Map.insert "widget" "datetime"
$ fv_meta $ defFieldView f
}
На фронтенде по JSON-описанию выбирается html-шаблон для отрисовки поля. Шаблоны хранятся в файле srv/resources/assets/template/fields/form.pug (в формате Pug).
Для выбора шаблона используются fv_type
и fv_meta.widget
из метаописания, а иногда даже и назание поля.
Шаблон для поля с fv_type = 'dictionary'
.field-template#dictionary-field-template
+dict("Local", "glyphicon-chevron-down")
Шаблон для поля c fv_meta.widget = 'datetime'
:
.field-template#datetime-field-template
+fieldControlGroup
+defaultInput("DateTime", "addMask: 'datetime',", "change")
Для полей требующих нестандартного отображения, вinstance Model
можно модифицировать JSON-описание.
modelView = \case
"" -> Just $ modifyView defaultView
[ hiddenIdent caseId
, readonly ctime
, readonly author
, readonly comment
]
Самые нестандартные модификации в Carma.Model.Case и в Carma.Model.Contract.
Например в Case
задаётся поведение поля contractIdentifier
— если в него начать вводить что-то, отправляется запрос на бэкенд, ищутся подходящие контракты и отображаются в виде выпадающего справочника.
,setType "dictionary" contractIdentifier
,dict contractIdentifier $ (dictOpt "") {dictType = Just "ContractsDict"}
Тут задаётся тип поля dictionary
, чтобы использовался шаблон #dictionary-field-template
. Дополнительно задаётся тип справочника ContractsDict
— там как раз описана отправка запросов на бэкенд и содержимое выпадающего списка: srv/resources/assets/script/dictionaries/contracts-dict.coffee