Вопрос

В 7.7 при разработке с "useFileContent = true" изменения js-ника не подхватываются при очистке кеша. Вместо этого необходимо постоянно выполнять операцию "Зафиксировать клиентские модули в БД".

Если это не критично, можна ли настроить поведение как в 7.6?

Ответ

В версии 7.7 появился модуль «SectionBundleModule», в котором лежат коды всех схем разделов и карточек (базовых). А также «ConfigurationBootstrap» в него входят базовые схемы, необходимые для работы системы.

Если Вы введете разработку функционала в базовых и замещенных схем, то необходимо в Web.config (...\Terrasoft.WebApp\Web.config) изменить в ключе «UseIncludeDependenciesSource» изменить признак на «false» (). Это связано с тем, что в версии 7.7 разработаны «SectionBundleModule» (для работы разделов/карточек/деталей) и «ConfigurationBootstrap» (минимальный набор для отображения интерфейса) для кэширования данных и тем самым увеличить быстродействие быстродействия.

Если Вы введете разработку функционала собственных схем (не базовых), то здесь необходимо применить изменения в среде разботки и очистить кэш браузера.

Нравится

Поделиться

0 комментариев
Показать все комментарии

Вопрос

Когда я создаю активности либо активность приходит в систему из Outlook, по какой-то причине в участниках этой же активности значится мой руководитель.

Ответ

Добавление участников активности при синхронизации календаря с Exchange происходит на основании электронного адреса. 

В данном случае проблема заключается в том, что на на детали [Средства связи] страницы контакта, который является вашим руководителем,  указан ваш электронный адрес. Для решения проблемы необходимо удалить ваш электронный адрес со страницы контакта — вашего руководителя.

Нравится

Поделиться

0 комментариев
Показать все комментарии

Вопрос

Есть ли какой-нибудь способ сделать карточку доступной только для редактирования?

Ответ

В BasePageV2 определен метод updateButtonsVisibility().

1 способ. Переопределить его, таким образом, чтобы ShowSaveButton, было false:

this.set("ShowSaveButton", false);

Однако в этом случае поля не будут заблокированы, но кнопки "Сохранить" не будет видно.

2 способ. Необходимо выполнять проверку при сохранении. В случае соответствия необходимым условиям выполнять родительский метод либо выводить сообщение о том, что редактирование запрещено.

Нравится

Поделиться

0 комментариев
Показать все комментарии

Вопрос

По умолчанию мастер мобильного приложения позволяет добавить в реестр раздела только два поля.

Пример:

Изображение удалено.

Возможно ли увеличить количество отображаемых полей? Если не через мастер, то через код.

Ответ

В реестре может отображаться не только колонка для отображения, но можно выводить и значения, сформированные на основании значений нескольких колонок. Для такого сложного форматирования, или отображения разных значений в зависимости от условий, значения колонок можно задавать в виде функций (используя методы Terrasoft.sdk.GridPage.setPrimaryColumn() и Terrasoft.sdk.GridPage.setSecondaryColumn()):

Terrasoft.sdk.GridPage.setPrimaryColumn('Account', {
	columns: ['Name', 'PrimaryContact'],
	convertFunction: function(values) {
		if (!Ext.isEmpty(values.PrimaryContact)) {
			return values.Name + ' (' + values.PrimaryContact + ')';
		} else {
			return values.Name;
		}
	}
});

Кроме того, можно указывать дополнительные колонки и при выборе значения поля-справочника. Делается это по аналогии с гридом, но только используется класс Terrasoft.sdk.LookupGridPage:

Terrasoft.sdk.LookupGridPage.setSecondaryColumn("Account", "PrimaryContact");

А вот альтернативный вариант расширения возможностей грида - изменение шаблона элементов грида:

Terrasoft.util.writeStyles(
	".div-table {",
		"display:table;",
		"width:100%;",
	"}",
	".div-table-row {",
		"display:table-row;",
		"width:100%;",
		"clear:both;",
	"}",
	".div-table-col {",
		"float:left;",
		"display:table-column;",
		"min-width:50%;",
	"}",
	".div-table-col-button {",
		"float:right;",
		"display:table-column;",
	"}"
);
Ext.define("MyCustomList", {
	override: "Ext.Terrasoft.List",
 
	initializeItemTpl: function() {
		this.callParent(arguments);
		var store = this.getStore();
		var model = store.getModel();
		var modelName = model.getName();
		if (modelName === "Account") {
			var tpl = this.getItemTpl();
			tpl.html =
			"<div class=\"x-list-item-tpl div-table\">" +
				"<div class=\"div-table-row\">" +
					"<div class=\"div-table-col\">{[this.applyPrimaryColumn(values)]}</div>" +
					"<div class=\"div-table-col-button\">{Phone}</div>" +
				"</div>" +
				"<div class=\"div-table-row\">" +
					"<div class=\"div-table-col\">{[this.applySecondaryColumn(values)]}</div>" +
					"<div class=\"div-table-col-button\">{Web}</div>" +
				"</div>" +
			"</div>";
		}
	}
 
});

 

Нравится

Поделиться

0 комментариев
Показать все комментарии

Задача

Необходимо реализовать поиск из командной строки доступной на странице портальных пользователей, по базе знаний, не только по основному полю (название), но и по содержимому статьи и публичным тегам.

Решение

Поиск можно доработать в «строке поиска по базе знаний» страницы портального пользователя. Это отдельный элемент, похожий на командную строку, использующий ее вид, но реализация его логики содержится в схеме KnowledgeBaseSearchModule.

Изображение удалено.

Эту страницу можно отладить и под обычным пользователем, в обычном интерфейсе, открыв ее как модуль данной ссылкой:

http://ваш-сайт/0/Nui/ViewModule.aspx#PortalMainPageModule/

Для реализации сложного фильтра вместо фильтра только по названию статьи, необходимо изменить следующий код, путем замещения базовой схемы KnowledgeBaseSearchModule:

/*sessionFilters.CustomFilters = {
    value: value,
    displayValue: value,
    primaryDisplayColumn: true
};*/
 
var filters = Ext.create("Terrasoft.FilterGroup");
filters.addItem(Terrasoft.createColumnFilterWithParameter(
    Terrasoft.ComparisonType.CONTAIN, "Notes", value));
filters.addItem(Terrasoft.createColumnFilterWithParameter(
    Terrasoft.ComparisonType.CONTAIN, "Name", value));
filters.addItem(Terrasoft.createColumnFilterWithParameter(
    Terrasoft.ComparisonType.CONTAIN, "Keywords", value));
filters.logicalOperation = Terrasoft.LogicalOperatorType.OR;
 
var serializationInfo = filters.getDefSerializationInfo();
serializationInfo.serializeFilterManagerInfo = true;
 
sessionFilters.CustomFilters = {
    "null": {
        "displayValue": value,
        "filter": filters.serialize(serializationInfo)
    }
};

 

Также для того, чтобы в колонку "Keywords" записывались публичные теги для последующего поиска по этой колонке, необходимо реализовать события изменения, добавления и удаления тегов базы знаний, путем создания их в замещающем объекте KnowledgeBaseInTagV2.

 

var userConnection = (UserConnection)HttpContext.Current.Session["UserConnection"];
Guid entityId = Entity.GetTypedColumnValue<Guid>("EntityId");
var esq = new EntitySchemaQuery(userConnection.EntitySchemaManager, "KnowledgeBaseInTagV2");
var publicTypeId = "D6FB4DE6-0809-41FE-A84F-6D245CBC5F32";
esq.AddColumn("Tag.Name");
var entityFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal,
    "Entity.Id", entityId);
var typeFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal,
    "Tag.Type", publicTypeId);
esq.Filters.Add(entityFilter);
esq.Filters.Add(typeFilter);
var entityCollection = esq.GetEntityCollection(userConnection);
string allTags = string.Empty;
foreach (var entity in entityCollection) {
    var tagName = entity.GetTypedColumnValue<string>("Tag_Name");
    allTags += tagName + ", ";
}
using (DBExecutor executor = userConnection.EnsureDBConnection()) {
    Update updateRelationshipQuery = new Update(userConnection, "KnowledgeBase");
    updateRelationshipQuery.Set("Keywords", Column.Parameter(allTags));
    updateRelationshipQuery.Where("Id").IsEqual(Column.Parameter(entityId));
    updateRelationshipQuery.Execute(executor);
}
return true;

И последнее, после публикации данных схем необходимо заполнить колонку "Keywords" публичными тегами для уже существующих записей базы знаний следующим скриптом:

UPDATE KnowledgeBase
SET Keywords = ISNULL(res.Tags, '')
FROM (SELECT a.Id, Tags = (SELECT stuff((
                select ', ' + Name from (SELECT t.Name FROM KnowledgeBaseTagV2 t WHERE
                                t.TypeId = 'D6FB4DE6-0809-41FE-A84F-6D245CBC5F32'
                                and t.Id
                                IN (
                                                SELECT e.TagId FROM KnowledgeBaseInTagV2 e WHERE e.EntityId = a.Id
                                )
) tb FOR XML PATH('')), 1, 2, ''))
FROM KnowledgeBase a
GROUP BY a.Id) res
WHERE res.ID = KnowledgeBase.Id

Где 'D6FB4DE6-0809-41FE-A84F-6D245CBC5F32' идентификатор типа "публичный тег".

Необходимые условия

Версия приложения со страницей портального пользователя и базовой схемой KnowledgeBaseSearchModule.

Нравится

Поделиться

0 комментариев
Показать все комментарии

Вопрос

У нас возникла задача программно запретить редактирование поля "Поставщика" на странице договора (ContractPage) при наступлении определенных условий. Все попытки сделать что-то вроде this.get или find('Supplier') и установить ему enabled или IsEnabled или всё что удалось нагуглить - не работает. 

При этом, если очистить поле поставщика, то его платежные реквизиты успешно блокируются, т.е. такая возможность у вас реализована. Как нам научиться ей пользоваться? Причем нужно именно программно, а не через привязки и прочее, т.к. условия запрета довольно сложные и могут меняться с течением времени и требовать запросов к базе и т.д.

Ответ

Данную возможность можно реализовать следующими способами:

var supp = this.find('Supplier');
supp.customConfig = {
    enabled: { bindTo: 'methodName''}
}

или

var supp = this.find('Supplier');
supp.customConfig = {
    enabled: false
}

Следующий пример кода демонстрирует блокирование поля "Поставщик" если значение поля "Номер" не равняется 2:

var supp = this.find('Supplier');
supp.customConfig = {
    enabled: { bindTo: 'test'}
}
this.methods.test = function(){ return this.get('Number') == '2' };

 

Нравится

Поделиться

0 комментариев
Показать все комментарии

Вопрос

Как добавить или изменить CSS стиль

Ответ

Чтобы добавить любой необходимый стиль необходимо:

1) Создать новый модуль. Добавить css стиль на вкладку Less. Рекомендуется использовать следующую структуру:

body[OldUI=false][CustomUI="true"] {
    .control-width-15 .t-label {
        color: #7FFF00;
    }
}

 Изображение удалено.

2) Создайте необходимую замещающую страницу используя пункт "Замещающий клиентский модуль". Например, необходимо заместить модуль BasePageV2. Добавьте модуль из первого шага в define замещающей страницы.

Переопределите метод init() и вызовите метод setAttributeToBody() чтобы добавить ваш стиль к body.

define("BasePageV2", ["css!UsrBasePageV2CSS"],
    function() {
        return {
            messages: {},
            mixins: {},
            attributes: {},
            methods: {
                init: function() {
                    this.callParent(arguments);
                    this.initializeCustomCss();
                },
                initializeCustomCss: function() {
                    Terrasoft.utils.dom.setAttributeToBody("CustomUI", true);
                }
            },
            diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
        };
});

 Изображение удалено.

3) Обновите страницу.

Изображение удалено.

Нравится

Поделиться

2 комментария

Это применяется во всех разделах. Если это необходимо в одном разделе, этот вариант не работает

А если замещать не BasePageV2, а свою страницу?

В конфигурации достаточно схем с названиями, оканчивающимися на CSS, в которых вносятся изменения стилей для конкретных схем. Например, AccountRelationshipDetailCss добавляет стили, специфичные для этой детали:

.account-relationship.detail {
	.relationship-mode-button {
		border-top-right-radius: 1px;
		border-bottom-right-radius: 1px;
	}
	.datagrid-mode-button {
		border-top-left-radius: 1px;
		border-bottom-left-radius: 1px;
	}
	.relationship-mode-button, .datagrid-mode-button {
		padding-left: 0.308em;
		padding-right: 0.462em;
	}
	.mode-button-pressed {
		background: #e4eaf9;
	}
	.account-relationship-chart {
		height: 450px;
	}
}

Затем в основной схеме этой детали AccountRelationshipDetailV2 подключается эта схема со стилями:

define("AccountRelationshipDetailV2", ["AccountRelationshipDetailV2Resources", "MiniPageUtilities",
	"ConfigurationDiagramGenerator", "RelationshipDiagramViewModel", "RelationshipDiagram",
	"LookupQuickAddMixin", "RelationshipChartGenerator", "RelationshipChart",
	"css!AccountRelationshipDetailCss"
], function() {

И так для конкретного элемента, например, кнопки, использовать стили оттуда:

{
 "operation": "insert",
 "name": "RelationshipModeButton",
 "parentName": "Detail",
 "propertyName": "tools",
 "values": {
	"itemType": this.Terrasoft.ViewItemType.BUTTON,
	"hint": {"bindTo": "Resources.Strings.DiagramViewButtonHint"},
	"click": {
		"bindTo": "setRelationshipMode"
	},
	"visible": {
		"bindTo": "getModeButtonsVisible"
	},
	"pressed": {
		"bindTo": "getRelationshipButtonPressed"
	},
	"classes": {
		"wrapperClass": ["relationship-mode-button"],
		"pressedClass": ["mode-button-pressed"]
	},
	"controlConfig": {
		"imageConfig": {
 "bindTo": "Resources.Images.RelationshipViewIcon"
		}
	},
	"markerValue": relationshipMode.Relationship
 }
{

 

Показать все комментарии

Вопрос

В разделе Активности, вкладке «Связи» необходимо убрать привязку к Документам и Лидам. 

Ответ

Запрошенные колонки можно удалить из детали «Связи» для Активностей, следующим запросом в базу данных:

DELETE FROM EntityConnection WHERE SysEntitySchemaUId = 'c449d832-a4cc-4b01-b9d5-8a12c42a9f89'
AND (ColumnUId = 'd6e94162-4354-413a-bc84-e118df5e852e'
OR ColumnUId = 'f6137557-741e-42f8-8bf6-69b2524a83f7')

 

Нравится

Поделиться

3 комментария

Дополню.

 

Id колонки смотреть в SysEntitySchemaReference.ColumnUId

например,

select distinct ColumnName , ColumnUId from SysEntitySchemaReference
where SysSchemaId in (select id from SysSchema where Name = 'Activity')
order by ColumnName

 

Id объекта будет в выборке

select [UId] from SysSchema where Name = 'Activity'

 

Доброго времени суток! А если скрыть, не удалять? 

Алексей, добрый день! 

 

Можете переопределить\доработать метод: loadColumnValues

Если из коллекции, после получения данных, но до её перебора “collection.each(function(item)…” удалить какой-то элемент, к примеру:

collection.collection.removeAt(1);

То этот элемент связи не будет обработан и показан на детали.

Показать все комментарии

Вопрос

Как отключить сборку клиентских скриптов в all-combined.js

Ответ

Для решения данного вопроса необходимо в Web.config (...\Terrasoft.WebApp\) добавить ключ в блок .

Хотелось бы отметить, что данное изменение в приложение повлияет на производительность приложения в целом.

Для увеличения производительности как раз и был создан all-combined.js.

Нравится

Поделиться

0 комментариев
Показать все комментарии

Вопрос

Подскажите пожалуйста, как сделать поле-выпадающий список из поля-справочника в редактируемом реестре версии 7.7.0.2293 SalesEnterprise + Marketing + CustomerCenter? Я сделал редактируемый реестр активностей, в карточке активности поле "Состояние" - выпадающий список. Но в редактируемом реестре это же поле представляет собой классический лукап с открываюшимся лукапным окном.

P.S. Решение полезно если страницы редактирования нет, или их много, или они базовые.

Ответ

Можно переопределить метод generateActiveRowControlsConfig() в схеме детали, и в нужных случаях, передавать нужный дополнительный конфиг.

В вашем случае можно добавить:

if (columnName = "Status") {
 
   cellConfig.contentType = Terrasoft.ContentType.ENUM;
 
}

Сразу после создания в нем cellConfig.

Исходный код можно взять из схемы ConfigurationGridUtilities, если он отличается от того что будет в предоставленном примере.

Пример схемы детали, на которой все тестировалось, включая превращение грида в редактируемый и переопределение generateActiveRowControlsConfig:

define("UsrSchema1Detail", ["terrasoft", "BusinessRulesApplierV2", "ConfigurationEnums", "BusinessRuleModule",
    "GridUtilitiesV2", "ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"], function(
        Terrasoft, BusinessRulesApplier, ConfigurationEnums, BusinessRuleModule) {
    return {
        entitySchemaName: "Activity",
        attributes: {
         "IsEditable": {
            dataValueType: Terrasoft.DataValueType.BOOLEAN,
            type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
            value: true
         }
        },
        mixins: {
         ConfigurationGridUtilites: "Terrasoft.ConfigurationGridUtilities"
        },
        details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[
            {
            "operation": "merge",
            "name": "DataGrid",
            "values": {
               "className": "Terrasoft.ConfigurationGrid",
               "generator": "ConfigurationGridGenerator.generatePartial",
               "generateControlsConfig": {"bindTo": "generatActiveRowControlsConfig"},
               "changeRow": {"bindTo": "changeRow"},
               "unSelectRow": {"bindTo": "unSelectRow"},
               "onGridClick": {"bindTo": "onGridClick"},
               "activeRowActions": [
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "save",
                     "markerValue": "save",
                     "imageConfig": {"bindTo": "Resources.Images.SaveIcon"}
                  },
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "cancel",
                     "markerValue": "cancel",
                     "imageConfig": {"bindTo": "Resources.Images.CancelIcon"}
                  },
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "remove",
                     "markerValue": "remove",
                     "imageConfig": {"bindTo": "Resources.Images.RemoveIcon"}
                  }
               ],
               "initActiveRowKeyMap": {"bindTo": "initActiveRowKeyMap"},
               "activeRowAction": {"bindTo": "onActiveRowAction"},
               "multiSelect": false
            }
         }
        ]/**SCHEMA_DIFF*/,
        methods: {
            generateActiveRowControlsConfig: function(id, columnsConfig, rowConfig) {
                this.columnsConfig = columnsConfig;
                var gridLayoutItems = [];
                var currentColumnIndex = 0;
                this.Terrasoft.each(columnsConfig, function(columnConfig) {
                    var columnName = columnConfig.key[0].name.bindTo;
                    var column = this.getColumnByColumnName(columnName);
                    var cellConfig = this.getCellControlsConfig(column);
 
                    cellConfig = this.Ext.apply({
                        layout: {
                            colSpan: columnConfig.cols,
                            column: currentColumnIndex,
                            row: 0,
                            rowSpan: 1
                        }
                    }, cellConfig);
 
                    if (columnName = "Status") {
                        cellConfig.contentType = Terrasoft.ContentType.ENUM;
                    }
 
                    gridLayoutItems.push(cellConfig);
                    currentColumnIndex += columnConfig.cols;
                }, this);
                var gridData = this.getGridData();
                var activeRow = gridData.get(id);
                var rowClass = {prototype: activeRow};
                BusinessRulesApplier.applyRules(rowClass, gridLayoutItems);
                var viewGenerator = this.Ext.create("Terrasoft.ViewGenerator");
                viewGenerator.viewModelClass = {prototype: this};
                var gridLayoutConfig = viewGenerator.generateGridLayout({
                    name: this.name,
                    items: gridLayoutItems
                });
                rowConfig.push(gridLayoutConfig);
            },
        }
    };
});

 

Нравится

Поделиться

0 комментариев
Показать все комментарии