Урок 20. Пользовательские настройки
В этом уроке мы создадим карточку для редактирования пользовательских настроек, в которой каждый пользователь сможет настроить индивидуальные параметры интерфейса. К таким параметрам относится временная зона, относительно которой будут отображаться все даты со временем, и язык интерфейса.
Если хотите начать практику с этого урока, то вам необходимо развернуть учебный проект по инструкции в статье Разворачивание проекта.
При разворачивании проекта используйте backup базы данных, который можете найти в архиве из раздела Ответы прошлого урока. Скопируйте папки Forms, Workflow и Patterns в папку с развернутым проектом, например, в папку D:\WT\Projects\Template\Projects\1. Template.
Инструкция по подключению шаблонов находится по ссылке.
Начнем с настройки прав доступа к новой функциональности.
Права доступа
Перейдем в файл описания работы серверной части приложения (Template.xml) .
Добавим точку доступа UserSettingsEditAccessPoint для просмотра и редактирования пользовательских настроек.
Создадим разрешение UserSettingsPermission, в которое добавим эту точку доступа. Добавим это разрешение в таблицу template.permission и настроим права доступа для пользовательских групп:
Теперь при добавлении новой функциональности необходимо каждый раз выполнять подобные запросы.
Часовой пояс
В уроках первого блока мы затрагивали тему временных зон и дат со временем. А в этом уроке предоставим пользователю возможность менять временную зону, в которой он хотел бы работать с датами со временем на формах. Это актуально, когда бизнес-процесс предполагает распределенную систему офисов: кол-центр, обрабатывающий заявки, находится в одном часовом поясе, а исполнители заявок в других временных зонах.
В приложении "Временные зоны" собрана полная информация о работе с датами со временем в платформе WT.
Форма
Создайте форму для редактирования пользовательских настроек (TemplateUserSettings.xml):
На главной форме (TemplateStart.xml) в меню добавьте пункт Опции -> Пользовательские настройки..., по которому будет открываться новая форма. Не забудьте использовать UserSettingsEditAccessPoint, чтобы ограничить доступ к пункту меню.
Запросы
Добавим запрос на получение списка часовых поясов:
Добавим запросы на чтение и изменение значения пользовательской временной зоны:
Добавьте три новых запроса в UserSettingsPermission.
Формы
Если пользователь изменил свой часовой пояс в настройках, то необходимо перезапустить приложение, чтобы новые настройки применились.
Добавим условие проверки изменения часового пояса:
Добавим команду отображения сообщения, чтобы уведомить пользователя о необходимости перезапустить программу при сохранении изменений:
Скорректируем команду SaveSequentialCommand:
Запустите приложение и проверьте смену часового пояса.
Мультиязычность
Помимо выбора собственной часовой зоны пользователь может настраивать язык интерфейса своей клиентской части.
Настройка языка
Переделайте форму пользовательских настроек, добавив выпадающий список "Язык":
Добавим запрос на получения списка поддерживаемых языков:
Не забудьте добавить этот запрос в UserSettingsPermission.
В запросы UserSettingsSelectSqlQuery и UserSettingsUpdateSqlQuery добавим поле LanguageId:
Чтобы стартовая форма узнала об изменении языка пользователя, необходимо внести доработки.
Заменим параметр Updated на параметр LanguageUpdated - так будет более наглядно:
Скорректируйте команду типа ValueSetCommand, которая будет присваивать этому параметру значение True, если значение языка изменилось.
Добавим условие проверки изменения зыка:
Скорректируем команду SaveSequentialCommand:
Изменение языка приложения
Скорректируем представление template.user_info, расширив его новыми полями language_id и language_code:
В серверном xml-файле скорректируем запрос UserCurrentSelectSqlQuery, добавив поле LanguageCode:
Перейдем в файл стартовой формы и в UserCurrentPrimaryGetDataConnection добавим новое поле LanguageCode:
Создадим команду обновления для UserCurrentPrimaryGetDataConnection, удалив его из команды AllPrimaryGetDataConnectionRefreshCommand:
Создадим команду типа LocaleSetCommand, с помощью которой будем устанавливать локаль и язык перевода для всего приложения:
Соберем обе команды в одну последовательность:
Добавим Execution на параметр LanguageUpdated команды UserSettingsFormShowCommand:
Добавим вызов команды LocaleSequentialCommand в Execution, которые срабатывают на команды LoginFormShowCommand и ReloginFormShowCommand - тем самым мы будем задавать настройки текущего пользователя при его аутентификации в программе.
Доработка форм
Чтобы интерфейс приложения поддерживал различные языки, необходимо организовать файлы строковых ресурсов и на формах указать привязку к нужным ресурсам.
Файлы строковых ресурсов
Скачайте архив с файлами строковых ресурсов и распакуйте его в папку с формами проекта (\Template\Projects\1. Template\Forms).
В папке Language вы найдете файлы:
По договоренности внутри компании: файлы ru.wxlf и en.wxlf используем для задания строковых ресурсов для форм, а файлы object-ru.wxlf и object-en.wxlf - для кастомных элементов (команд, объектов и т.д.), которые рассмотрим в одном из следующих уроков. На самом деле платформа считывает из папки Forms\Language все файлы одной локали и записывает их в один словарь. И файлов по одной локали может быть сколько угодно - отбор происходит по имени файла, оно должно оканчиваться именем локали (ru/en).
Структура файлов одинакова:
Тэг <Wxliff>
содержит список вложенных тэгов <Context>
. Каждый такой тэг привязывается к конкретному файлу, имя которого указывается в атрибуте File
. Если атрибут отсутствует, то такой контекст считается общим для всех форм.
Каждый контекст содержит набор строковых ресурсов, представленных тэгом <Text>
, у которого есть атрибуты:
Id
- уникальный (в рамках контекста) идентификатор ресурса, по которому форма будет его искать. Обязательный атрибут.
Тэг <Text>
содержит тэги:
<Source>
- оригинальный текст, который выступает в качестве подсказки в файле перевода. Необязательный тэг;<Target>
- целевая строка, которая будет использоваться на форме.
В файлах ru.wxlf и en.wxlf есть начальные данные, и указаны два тэга <Context>
: общий контекст с ресурсами, которые используются на многих формах, и контекст для формы TemplateUserSettings.xml.
Использование строкового ресурса на форме
Давайте перейдем в файл формы пользовательских настроек (TemplateUserSettings.xml) и на его примере разберем использование строковых ресурсов.
В файле формы необходимо все строковые константы заменить тэгом <Text>
, значением которого будет строка:
Например, на форме есть параметр Title:
Заменим его описание:
В файлах ru.wxlf и en.wxlf в соответствующем контексте есть строковые ресурсы:
Замените текст объектов LanguageLabel и TimeZoneInfoLabel, используя идентификатор строковых ресурсов из контекста данной формы.
А для текста кнопки SaveButton используйте идентификатор строкового ресурса из общего контекста:
Запустите приложение и проверьте смену языка.
Как это работает
В процессе загрузки форма считывает файл строковых ресурсов, соответствующий установленной локали приложения, и ищет в нем ресурс с указанным идентификатором.
Сначала форма ищет в общем контексте, если там нет нужного ресурса, то продолжает искать в собственном контексте.
Когда форма находит подходящий ресурс, то берет из него значение тэга <Target> и использует это значение в своих элементах.
Если форма не находит подходящего ресурса в файле строковых ресурсов, то использует текст, который указали в качестве значения тэга <Text>
.
Другие замены
Продолжим работать с формой пользовательских настроек (TemplateUserSettings.xml).
На форме есть команды SaveOnCloseMessageBoxCommand и CloseOnCloseMessageBoxCommand - в них тоже необходимо подобным образом заменить значения тэгов <Caption>
и <Text>
:
Текст кнопок в диалоговом окне отображается на том языке, который задан в настройках операционной системы.
Аналогичным образом сделайте с командой UserTimeZoneInfoChangedMessageBoxCommand.
Замена констант
На самом деле подобные подстановки ресурсов мы можем делать с любыми константами на форме.
В качестве примера мы можем привязать ширину кнопки SaveButton к локали.
Добавим в файлы строковых ресурсов значения:
Запустите приложение и проверьте отображение кнопки при использовании разных языков:
Эти изменения можно убрать - они носили демонстрационный характер.
ComboBox
Перейдем в файл карточки назначения платежа (TemplateOperationEdit.xml) и найдем там описание объекта CategoryComboBox.
В объекте используется вложенный тэг <NullValue>
для настройки отображения NULL-значения выпадающего списка:
Использование атрибута Title
в тэге <NullValue>
не позволяет заменять его значение на строковый ресурс. Поэтому заменим атрибут Title
на тэг <NullValueTitle>
. Это позволит динамически задавать отображение NULL-значения объекта, в том числе для поддержки мультиязычности.
В файлах строковых ресурсов в общем контексте уже есть нужное значение. Его и будем использовать:
На некоторых формах у нас есть фильтр архивных актуальных записей (ArchiveFilterComboBox):
При поддержке мультиязычности он примет вид:
Поддержка языков в SQL-запросах
В некоторых запросах мы уже сталкивались с функцией public.string_value(character varying, integer), которая относительно настроек языка пользователя возвращала по ключу из таблицы public.strings соответствующую строку.
В этой таблице хранятся системные строки, редактировать которые пользователи не могут.
Например, в запросе LoadModeSelectSqlQuery для получения списка доступных режимов загрузки данных мы использовали эту функцию. В таблице уже были необходимые строковые ресурсы:
В своей практике мы используем функцию public.check_strings(), которая проверяет наличие переводов для всех языков и вернет список ключей, у которых отсутствует перевод для какого-либо языка.
Ниже приведен код этой функции, чтобы вы могли добавить ее в свой проект и использовать для проверки строк перевода.
Самостоятельно
Переведите все формы на поддержку языков.
Не забудьте перевести строковые константы в запросах для списка назначений платежей и отчета по бюджету. Добавьте строковые ресурсы в таблицу public.strings и используйте функцию public.string_value(character varying, integer) для получения нужного значения, как это сделано в запросе TimeZoneInfoSelectSqlQuery и LoadModeSelectSqlQuery.
Также добавьте перевод для описания динамических прав доступа - запрос PermissionBlockItemSelectSqlQuery. Используйте значения в колонках id_title таблиц template.permission_block и template.permission_block_item в качестве ключа для строковых ресурсов.
На форму настроек добавьте возможность редактировать временную зону, выбранную по умолчанию для новых пользователей.
Пользовательские настройки форм
Дополнительно к пользовательским настройкам можно отнести настройки видимости, порядка и ширины колонок таблицы DatabaseTable, сортировку строк и фильтры в таблице. Также можно запоминать состояние формы и значения переменных, а при следующем открытии формы восстанавливать их.
Все это можно сохранять для каждого пользователя отдельно.
Настройки таблиц
Для сохранения настроек в таблице DatabaseTable реализован вложенный тэг <SaveOnFormClose>
:
Информация о настройках пишется в таблицу public.user_form_info. Для каждой формы и каждого пользователя отдельная запись.
Давайте перейдем в файл списка клиентов (TemplateClientList.xml) и в таблицу ClientDatabaseTable добавим тэг <SaveOnFormClose>
.
Когда откроем и закроем окно списка клиентов, в базе данных в таблице появится запись:
Значение в колонке name совпадает со значение в атрибуте Name
тэга <Form>
.
Так как мы просто открыли и закрыли форму, то в колонке tables_info хранится информация только о колонках:
Чтобы можно было менять размер колонок, необходимо в таблице атрибуту Value
тэга <AllowResizeColumns>
поставить значение True, а для колонки атрибуту Value
тэга <AutoSizeMode>
поставить значение None.
Давайте это сделаем для колонки CityTitle (Город). Откроем форму списка клиентов, изменим ширину колонки "Город" и закроем окно. При повторном открытии формы мы увидим, что размер колонки сохранился, а в базе будет запись вида:
Добавим настраиваемый фильтр в таблицу через контекстное меню, кликнув ПКМ по заголовку таблицы:
В таблицу сохранится запись вида:
Давайте сбросим фильтрацию и добавим настраиваемую сортировку:
Теперь в таблицу сохранится запись вида:
Состояние формы
Чтобы сохранять состояние формы, у тэга <Form>
есть атрибут RestoreLastFormState
. Если значение атрибута равно True, то состояние формы будет запоминаться в колонку form_state таблицы public.user_form_info.
Поддерживается три состояния:
0 - окно с размерами по умолчанию (Normal);
1 - свернутое окно (Minimized);
2 - развернутое окно (Maximized).
Значение Variable
Для сохранения значения переменной Variable реализован вложенный тэг <SaveOnFormClose>
:
Значения переменных сохраняются в колонку variables_info таблицы public.user_form_info.
На форме списка клиентов создайте тестовую переменную, которой укажите тэг <SaveOnFormClose>
со значением True и каким-нибудь значением. Откройте и закройте форму списка, а затем проверьте содержимое таблицы public.user_form_info.
Итоги
В этом уроке мы познакомились с поддержкой языков в платформе WT и реализовали пользовательские настройки. Узнали, что на формах можно сохранять настройки видимости, ширину и порядок столбцов таблицы, фильтры и сортировку строк в DatabaseTable, а также состояние самой формы.
Ответы
В архиве присутствуют xml-файлы форм и серверный xml-файл, также лежит бэкап базы данных и файл с запросами на изменение структуры базы данных - с помощью файлов можете проверить себя.
Last updated