Skip to content
Max Taldykin edited this page May 5, 2020 · 1 revision

Формочки в 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

src

Тут тип поля, его название в БД и комментарий. Эта информация дальше превращается в 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
    }

src

А вот так 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
    }

src

На фронтенде по 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")

src

Шаблон для поля c fv_meta.widget = 'datetime':

.field-template#datetime-field-template
  +fieldControlGroup
    +defaultInput("DateTime", "addMask: 'datetime',", "change")

src


Для полей требующих нестандартного отображения, вinstance Model можно модифицировать JSON-описание.

  modelView = \case
    "" -> Just $ modifyView defaultView
          [ hiddenIdent caseId
          , readonly ctime
          , readonly author
          , readonly comment
          ]

src


Самые нестандартные модификации в Carma.Model.Case и в Carma.Model.Contract.

Например в Case задаётся поведение поля contractIdentifier — если в него начать вводить что-то, отправляется запрос на бэкенд, ищутся подходящие контракты и отображаются в виде выпадающего справочника.

  ,setType "dictionary" contractIdentifier
  ,dict contractIdentifier $ (dictOpt "") {dictType = Just "ContractsDict"}

src

Тут задаётся тип поля dictionary, чтобы использовался шаблон #dictionary-field-template. Дополнительно задаётся тип справочника ContractsDict — там как раз описана отправка запросов на бэкенд и содержимое выпадающего списка: srv/resources/assets/script/dictionaries/contracts-dict.coffee

Clone this wiki locally