Добрый вечер.

 

Подскажите, пжл, куда в Системе необходимо смотреть (где производить настройки/разработку), чтобы выполнить следующие требования в представлении "Календарь" раздела "Активности":

- закрепить шапку календаря (при наличии большого количества многодневных задач шапка после прокрутки скрывается, оставаясь "сверху")

- отсортировать записи не по полю "Начало", а по полю "Завершения"

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

Нравится

5 комментариев
Лучший ответ

Попробовал уменьшить окно браузера.

Да, похоже шапка вместе с многодневными задачами закрепляется сверху над обычными задачами. А если они сами не влазят целиком, то вместе прокручиваются и шапка исчезает, остаётся только блок фильтров и всё, что выше его.

 

Это компонент ядра Terrasoft.controls.ScheduleEdit, он реализован в файле https://сайт/0/core/hash/Terrasoft/controls/schedule-edit/schedule-edit…

 

Там, если смотреть HTML-код страницы, есть три блока, сверху вниз: title-area, multi-day-item-area, scroll-area. Даже по названию видно, что прокручиваться предназначен третий, с обычными задачами.

 

То есть, это код ядра, не конфигурации.

Сортировка по началу, видимо, там же:

	/**
	 * Returns the sorted list of calendar items.
	 * @private
	 * @param {Array} schedulerItemList List of calendar items.
	 * @return {Array} Sorted list of calendar items.
	 */
	sortScheduleItemList: function(schedulerItemList) {
		const sortItemList = [];
		Terrasoft.each(schedulerItemList, function(item) {
			if (!item.isMultiDayItem()) {
				sortItemList.push(item);
			}
		});
		sortItemList.sort(this.sortScheduleItemListByStartDate);
		return sortItemList;
	},
 
	/**
	 * Returns the result of comparing 2 calendar items by date.
	 * @private
	 * @param {Object} itemA Item #.
	 * @param {Object} itemB Item B.
	 * @return {Array} The result of comparing 2 calendar items by date.
	 */
	sortScheduleItemListByStartDate: function(itemA, itemB) {
		let result = 0;
		const itemAStartDate = itemA.startDate;
		const itemADuration = itemA.dueDate - itemAStartDate;
		const itemBStartDate = itemB.startDate;
		const itemBDuration = itemB.dueDate - itemBStartDate;
		if ((itemAStartDate === itemBStartDate) && (itemADuration === itemBDuration)) {
			result = 0;
		} else if (itemAStartDate > itemBStartDate) {
			result = 1;
		} else if (itemAStartDate < itemBStartDate) {
			result = -1;
		} else if (itemADuration > itemBDuration) {
			result = -1;
		} else if (itemADuration < itemBDuration) {
			result = 1;
		}
		return result;
	},

 

Уточните, где именно на скриншоте у Вас скрылась шапка? И блок фильтрации, и многодневные задачи там видны.

 

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

Зверев Александр,

Вот как раз, если много задач, то при пролистывании ползунком скрывается шапка, прилагаю скриншот:

// + где настроить, чтобы  <отсортировать записи не по полю "Начало", а по полю "Завершения">/

Попробовал уменьшить окно браузера.

Да, похоже шапка вместе с многодневными задачами закрепляется сверху над обычными задачами. А если они сами не влазят целиком, то вместе прокручиваются и шапка исчезает, остаётся только блок фильтров и всё, что выше его.

 

Это компонент ядра Terrasoft.controls.ScheduleEdit, он реализован в файле https://сайт/0/core/hash/Terrasoft/controls/schedule-edit/schedule-edit…

 

Там, если смотреть HTML-код страницы, есть три блока, сверху вниз: title-area, multi-day-item-area, scroll-area. Даже по названию видно, что прокручиваться предназначен третий, с обычными задачами.

 

То есть, это код ядра, не конфигурации.

Сортировка по началу, видимо, там же:

	/**
	 * Returns the sorted list of calendar items.
	 * @private
	 * @param {Array} schedulerItemList List of calendar items.
	 * @return {Array} Sorted list of calendar items.
	 */
	sortScheduleItemList: function(schedulerItemList) {
		const sortItemList = [];
		Terrasoft.each(schedulerItemList, function(item) {
			if (!item.isMultiDayItem()) {
				sortItemList.push(item);
			}
		});
		sortItemList.sort(this.sortScheduleItemListByStartDate);
		return sortItemList;
	},
 
	/**
	 * Returns the result of comparing 2 calendar items by date.
	 * @private
	 * @param {Object} itemA Item #.
	 * @param {Object} itemB Item B.
	 * @return {Array} The result of comparing 2 calendar items by date.
	 */
	sortScheduleItemListByStartDate: function(itemA, itemB) {
		let result = 0;
		const itemAStartDate = itemA.startDate;
		const itemADuration = itemA.dueDate - itemAStartDate;
		const itemBStartDate = itemB.startDate;
		const itemBDuration = itemB.dueDate - itemBStartDate;
		if ((itemAStartDate === itemBStartDate) &amp;&amp; (itemADuration === itemBDuration)) {
			result = 0;
		} else if (itemAStartDate &gt; itemBStartDate) {
			result = 1;
		} else if (itemAStartDate &lt; itemBStartDate) {
			result = -1;
		} else if (itemADuration &gt; itemBDuration) {
			result = -1;
		} else if (itemADuration &lt; itemBDuration) {
			result = 1;
		}
		return result;
	},

 

Зверев Александр,

Спасибо за ответ. Возможно ли запланировать в базовой функциональности фиксацию шапки календаря и возможность настройки сортировки?

Завёл идеи о шапке многодневных и способе сортировки.

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

Есть кейс - при создании активности с категорией "встреча" кроме ответственного эта встреча должна отобразиться в расписании у сотрудников, которые добавлены в "Участники". 

Фильтр типа "показать активности с категорией Встреча если там есть участник - текущий пользователь" не работает. 

Приходится создавать 2 встречи на каждого из участвующих во встрече. 

Нравится

1 комментарий

Здравствуйте, Улан!

Проверили данный кейс на версии 7.12.1. Создали активность с категорией встреча и несколькими участниками. Построили расширенный фильтр "показать активности с категорией Встреча если там есть участник - текущий пользователь". Созданная активность отобразилась. 

Рекомендуем Вам обратиться в службу технической поддержки по адресу support@terrasoft.ru для детального анализа.

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

Необходимо с определенной периодичностью (например 1 раз в день) экспортировать определенный справочник (с ранее подготовленным форматом экспорта) в xls/csv формате и ложить его на сервер, чтобы он был доступен по http. 

Подскажите как это можно реализовать?

Можно ли создать БП с действием "Запустить экспорт №3" и положить его на сервер

Как альтернатива - отправить экспортированный файл на определенную почту

Нравится

1 комментарий

Здравствуйте,

Такого функционала в приложении пока нет, но мы передадим данное пожелание в отдел разработки для реализации данного варианта автоматизации в будущих версиях приложения.

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

Нужно создать новый фильтр в расписании - рабочая неделя.
насколько я разобрался изменения нужно вносить в в замещающие модули FixedFilterViewModelV2 и FixedFilterViewV2, полностью скопировал код из родителей, дописал новый фильтр и сохранил. После обновления страницы в списку появился новый фильтр но пропали все другие, пустые строки, но когда на них нажимать фильтрование происходит. Также пропали иконки текущего дня, тек недели и месяца. Остался только выпадающий список с пустыми строками среди которых мой фильтр. Как сделать что бы все старое осталось и был мой новый фильтр?о

Нравится

12 комментариев

в модуль перенести все ресурсы

Так они переносятся при указании поля родительский объект

"Радчук Виталий Владимирович" написал:Так они переносятся при указании поля родительский объект

Поверьте мне, нет. С модулями все очень плохо на текущий момент.

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

И еще один болезненный вопрос. Как заставить бпм отобразить изменения? код сохраняю, компилирую все, обновляю с очисткой кеша, удаляю кеш цклинером - бесполезно, 0 реакции...

А если посмотреть код схемы в браузере, ваши изменения находит? Если переоткрыть схему в конфигурации снова, ваши изменения остались в ней?

А где изображения взять то? с родителя не скачаеш...

"Максим Шевченко" написал:А если посмотреть код схемы в браузере, ваши изменения находит?

нет
"Максим Шевченко" написал:Если переоткрыть схему в конфигурации снова, ваши изменения остались в ней?

да

"Радчук Виталий Владимирович" написал:А где изображения взять то? с родителя не скачаеш...

Откатите изменения, удалив данную схему замещения, после этого внесите любые изменения в любую другую js схему, сохраните, после чего почистите кеш браузера и перезайдите на сайт. И inspect-ом браузера найдите и скачайте все картинки что у Вас пропали после замещения.

"Радчук Виталий Владимирович" написал:Если переоткрыть схему в конфигурации снова, ваши изменения остались в ней?
да

Значит изменения сохранились. Почистите кеш браузера что бы увидеть их в браузере.

"Максим Шевченко" написал:Значит изменения сохранились. Почистите кеш браузера что бы увидеть их в браузере.

чистил, не помогало
"Максим Шевченко" написал:после этого внесите любые изменения в любую другую js схему, сохраните

по этой схеме иногда работает... крутая схема...

"Радчук Виталий Владимирович" написал:чистил, не помогало

Сложно в это поверить. Напишите в техническую поддержку Террасофт указав сайт и схему где сделаны изменения. Если они внесены и сохранены, они должны появится в браузере, другое дело что вы там написали, может быть просто код неккоректен.

"Радчук Виталий Владимирович" написал:по этой схеме иногда работает... крутая схема...

При удалении схем, на данный момент это единственный способ дать понять системе что что-то изменилось и нужно пересобрать все схемы.

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

Заполняем поле менеджер(пользователь системы), заполняем поле даты/время, при заполнении этого поля нужно проверить свободен ли в это время(и следующих 15 мин) менеджер, если да то делаем кнопку доступной.
Интересует как сделать саму проверку.

Нравится

9 комментариев

Добрый вечер, Виталий.

Для решения Вашей задачи необходимо:
1) Привязать доступность кнопки к булевому атрибуту, имеющему по умолчанию значение false.
2) При каждом изменении поля Дата/Время делать запрос к базе данных проверяя свободен ли он и на основании результат менять значение атрибута из пункта 1.

Вот что получилось:
var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "Activity"});
esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "Id");
esq.filters.addItem(this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL,
"Owner",
this.get("Owner").value
));
esq.filters.addItem(this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.Greater,
"StartDate",
new Date()
));
esq.getEntityCollection(
function(response) {
var e = response.collection.getByIndex(0).get("Id");
e = e + e;
},
this
);
на строке var e = response.collection.getByIndex(0).get("Id"); выбивает ошибку - елемент не найден, если убрать фильтр по дате - выбирает все как есть, значит проблема в фильтре, что я сделал не так? возможно формат другой? я не смог найти пример с датами

... жесть, не Greater а GREATER

так, наткнулся на другую проблему, как я понял оно работает:
формируем запрос и отправили его на сервер и когда придет ответ - обрабатываем его, но не ждем пока он придет код выполняется дальше. когда приходит ответ - выполняется функция "getEntityCollection( function(response". И тут 2 вопроса можно ли сделать так чтоб все висло и ждало пока придет ответ и как передать в эту функцию параметры

Виталий, javascript асинхронный по умолчанию и с этим ничего сделать нельзя.

По поводу параметров:

1) В метод getEntityCollection вторым параметром передается scope выполнения функции обратного вызова. Т.е. если в него передать this - функция сможет работать с любыми атрибутами или методами карточки.

2) Аналогично можно перед вызовом getEntityCollection закешировать this.
var scope = this;
Тогда можно будет получить или изменить любой атрибут обращаясь к scope внутри функции обратного вызова.
var param = scope.get("Owner");
scope.set("Owner", {id: "", displayValue: "Supervisor"})

да но что делать когда нужно выполнить вот такой код:

esq.getEntityCollection(
	function(response) {
		var ActivitytCount = response.collection.getByIndex(0).get("Id");
		if (ActivitytCount === 0) {
			this.callParent([function() {
				this.Terrasoft.chain(this.publishOnSaveEvents, function() {
					this.onSaved(callback, scope);
				}, this);
			}, this]);

выбивает ошибку:
TypeError: e is undefined

Как вариант зависания - используйте метод showBodyMask() перед вызовом getEntityCollection. Это позволит отобразить на карточке маску загрузки которая не позволит менять данные.

В функции обратного вызова скройте маску this.hideBodyMask()

this.showBodyMask();
esq.getEntityCollection(function(response) {
	//вычисления
	this.hideBodyMask()
}, this);

рекомендую также смотреть в сторону использования try catch что бы избежать вечной маски загрузки если в коллбэке возникнет ошибка

Ошибка в том, что вызвать callParent в функции обратного вызова невозможно, контекст уже утерян.

Пример решения (метод onEntityInitialized взят для примера):

onEntityInitialized: function() {
	if(this.get("test") === true){
		this.set("test", false);
		this.callParent([function() {
			this.Terrasoft.chain(this.publishOnSaveEvents, function() {
				this.onSaved(callback, scope);
			}, this);
		}, this]
                return;
	}
	esq.getEntityCollection(
		function(response) {
			var ActivitytCount = response.collection.getByIndex(0).get("Id");
			if (ActivitytCount === 0) {
				this.set("test", true)
				this.onEntityInitialized();
			}
		},
	this);
}

Вау! Никогда не использовал такую логику!!! Сработало, благодарю!

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

Добрый день!
Есть два вопроса по разделу планирование визитов в 7.6.

1)В разделе планирования визитов активности меняют цвет в соответствии со своим статусом. Этот код размещен на schedule-item.js. Как можно его переопределить под свои нужды? Необходимо менять цвет активности по другому условию (например)

2) Необходимо запретить пользовательское изменение размера активности на расписании. Т.е., изначально в активность вместо времени начала и конца сообщается время начала и ее длительность. Пользователь не должен иметь возможности увеличить ее. Размер активности для каждого контрагента будет статичным и меняться только по изменении соответствующего поля в контрагенте.

Нравится

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

Никита, непонятно, о каких визитах идет речь.

Визиты появились в версии 7.6.

По второму вопросу - какой у Вас конкретный вопрос?

"Безродный Андрей" написал:

Никита, непонятно, о каких визитах идет речь.

Визиты появились в версии 7.6.

По второму вопросу - какой у Вас конкретный вопрос?


Я наверное перепутал версию. Приложил скриншот по поводу 1 вопроса.
Второй вопрос. "Необходимо запретить пользовательское изменение размера активности на расписании." Как это можно сделать?

Никита, добрый день!

Похожая тема по изменению цвета в активностях обсуждалась здесь. Возможно, это поможет Вам в решении проблемы.

Что касается второго вопроса - есть вариант сделать объект "Активность" администрируемым по колонкам и раздать доступ только на просмотр колонок "Начало" и "Завершение" для всех пользователей. Хотя визуально размер активности в расписании будет изменяться, фактически в этих полях будут оставаться прежние значения.

Если необходимо, чтобы элемент активности даже визуально не изменял свой размер, это возможно только путём переопределения методов компонента Terrasoft.ScheduleItem.

Спасибо за помощь!

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

Здравствуйте!

Столкнулись с задачей, когда необходимо переделать базовую фильтрацию "FixedFilters" для расписания. Идея в том, чтобы вместо кнопок "Сегодня" и "Текущая неделя" сделать 4 кнопки, которые будут показывать определенные недели в году (например кнопка "1" будет показывать неделю, по которой была зарегистрирована 1ая запись для данного объекта). Подскажите, пожалуйста, как лучше всего будет организовать подобное?

Нравится

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

Никита, добрый день!

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

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

this.fixedFilterConfig = {
entitySchema: Activity,
filters: [
{
	  name: 'PeriodFilter',
	  caption: resources.localizableStrings.PeriodFilterCaption,
	  dataValueType: Terrasoft.DataValueType.DATE,
	  startDate: {
			   columnName: 'StartDate',
			   defValue: Terrasoft.startOfWeek(new Date())
	  },
	  dueDate: {
			   columnName: 'DueDate',
			   defValue: Terrasoft.endOfWeek(new Date())
	  }
},
{
	  name: 'Owner',
	  caption: resources.localizableStrings.OwnerFilterCaption,
	  columnName: 'Owner',
	  defValue: Terrasoft.SysValue.CURRENT_USER_CONTACT,
	  dataValueType: Terrasoft.DataValueType.LOOKUP,
	  filter: BaseFiltersGenerateModule.OwnerFilter,
	  appendFilter: function(filterInfo) {
			   var filter;
			   if (filterInfo.value && filterInfo.value.length > 0) {
						 filter = Terrasoft.createColumnInFilterWithParameters(
								  '[ActivityParticipant:Activity].Participant',
								  filterInfo.value);
			   }
			   return filter;
	  }
}
]
};

Дмитрий, спасибо за совет! Попробуем на основе этого что-то придумать.

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

Здравствуйте!
В разделе "Активности" есть представление "Планирование визитов". На нем расположен список контрагентов, расписание и карта.
Если я добавляю эти объекты в свой раздел,то они располагаются друг под другом. Подскажите, пожалуйста, где можно настроить их позиции так, чтобы они были как на планировании визитов (т.е., в строчку, а не столбиком)?

Нравится

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

Добрый день, Никита.

Скиньте, пожалуйста, скриншот того, как Вы добавляете объекты в свой раздел и как они располагаются друг под другом.

Если я правильно понял, то Вы имеете в виду объекты: реестр, расписание и карта. Если это те объекты, о которых речь, то их позиционирование регламентируется CSS стилями. Подробнее о расположении элементов в строку с помощью CSS можно почитать тут:
http://htmlbook.ru/samlayout/blochnaya-verstka/strochno-blochnye-elemen…
И по запросу в Google:
css div расположение элементов в строку

"E.Podkovka" написал:

Если я правильно понял, то Вы имеете в виду объекты: реестр, расписание и карта. Если это те объекты, о которых речь, то их позиционирование регламентируется CSS стилями.


Действительно, добавил свой модуль с разметкой и подключил его. Все заработало. Спасибо!

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

Здравствуйте. Есть задача запускать процесс по расписанию в ночное время или с определенной периодичностью (включая ночное время), когда пользователи в системе не активны.
Подскажите пожалуйста, как правильно запускать процесс(от фиксированного имени пользователя или текущего) и как настроить пул на iis, чтоб была возможность запускать процессы в любое время?

Планировал процесс следующим образом:

// Задание интервала запуска процесса (в минутах).
        int minutleyInterval = IntervalContentEngine;
        var jobName="sxContentEngineProcessJob";
        var jobGroup="RefreshFromContentEngineProcessGroup";
       
if(!AppScheduler.DoesJobExist(jobName,jobGroup)){

        // Добавление задания по запуску процесса в планировщик.
        AppScheduler.ScheduleMinutelyProcessJob(jobName, jobGroup, "sxContentEngineProcess",
            UserConnection.Workspace.Name, UserConnection.CurrentUser.Name, minutleyInterval);
}

Нравится

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

Здравствуйте, Александр!

Если у Вас on-demand, то следующий абзац можно упустить.
Для того, чтобы процессы постоянно, а главное вовремя, запускались, должны быть выполнены два условия:
1) Пул приложения должен быть запущен
2) Сайт должен работать

Чтобы выполнялось первое условие, установите таймаут простоя IIS равным 0:

Второй пункт выполняется практически всегда. У IIS есть особенность - он раз в сутки перезагружает пулы и, соответственно, сайт останавливается до следующего входа пользователя. Процессы тоже не запускаются.
Для того, чтобы после перезагрузки пула, процесс продолжал работать, в msdn создана эта тема.
В данной теме есть ссылка на бесплатную утилиту, которая постоянно опрашивает работает ли сайт.
Таким образом можно обеспечить постоянную работу сайта, а соответственно и запуск процессов.

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

Алексей, вроде бы получилось, спасибо!
Полностью проверить удастся завтра.
Также, если кому-то пригодится, smarterPing нужно устанавливать через имеющийся bat-файл из командной строки,запущенной от имени администратора.

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

Добрый день, друзья!
Есть необходимость вести учет занятости кабинетов предприятия (по аналогии с переговорками), с получением итогов - какие кабинеты больше используются.
У меня возникла идея создать кастомный тип активности "Кабинет", и привязать к нему 10 кабинетов, каждый из которых, является категорией данного типа с именем "Кабинет №1", "Кабинет №2" и .т.д.
Таким образом можно создавать в расписании эти активности, перетаскивать их и динамическими группами смотреть загрузку по кабинетам.
Однако я предвижу проблему, что разные пользователи смогут накладывать на одно и то же время активности одинаковой категории и может возникнуть путаница.
Подскажите, может я изобретаю велосипед, и все можно решить иначе и проще.
Спасибо!

Нравится

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

Скорее, тип будет стандартный "встреча", или "звонок", или какой-то еще, который нужен будет по данной активности.
Основным источником информации может быть новое поле "Кабинет", по которому и можно производить фильтрацию. И дополнительно писать скрипт, который проверяет, что в данном кабинете на то же время не запланировано других активностей

Спасибо

А почему просто не создать контакт с названием "Кабинет 1" и т.д. и добавлять его в деталь "участники активности". Тогда при фильтрации по отвественному "Кабинет 1" можно смотреть расписание, когда кабинет занят, а когда свободен. Также можно в последующем выстраивать аналитику по загруженности кабинетов.

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