Скрипт — это набор инструкций на C#, которые составляют тело скрытого внутреннего метода, затем компилируемого и выполняемого по триггерам.
Технически скрипты транслируются на внутренний промежуточный язык .NET - CIL.
Скрипты вызываются событиями в системе. На одно событие в рамках пространства может быть создано несколько автоматизаций.
Каждое событие имеет свой контекст - набор данных, связанный с ним. Контексты для разных событий отличаются.
Контекст передается в память выполняющегося скрипта в виде типизированного объекта. Доступ к контексту осуществляется через переменную e.
debug($"Пространство: {e.WorkspaceKey}");
Когда триггером автоматизации является событие Создание задачи, передаются следующие данные события:
public class WorkitemCreatedEventContext : BaseWorkitemEventContext{public Guid WorkitemId { get; init; } // Идентификатор созданной задачиpublic string WorkitemKey { get; init; } // Ключ созданной задачиpublic string WorkitemName { get; init; } // Название созданной задачиpublic required string? WorkitemDescription { get; set; } // Описание созданной задачиpublic Guid? WorkitemAssigneeId { get; init; } // Идентификатор ответсвенного на задачеpublic Guid WorkitemTypeId { get; init; } // Идентификатор типа задачиpublic required DateTime WorkitemCreationDate { get; set; } // Дата создания задачиpublic required Guid? WorkitemWorkflowId { get; init; } // Идентификатор рабочего процесса задачиpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Событиями изменения задачи являются:
- Изменение родительской задачи или папки;
- Изменение типа задачи;
- Изменение процесса;
- Изменение статуса;
- Изменение имени;
- Изменение описания;
- Изменение ответственного;
- Изменение даты начала;
- Изменение даты выполнения;
- Изменение оценки в часах;
- Изменение оценки в сторипоинтах;
- Изменение спринта;
- Изменение значения прогресса;
- Изменение пользовательского атрибута.
Для этих событий передаются следующие данные контекста:
public class WorkitemUpdatedEventContext : BaseWorkitemEventContext{public object? OldValue { get; init; } // Значение параметра до измененияpublic object? NewValue { get; init; } // Значение параметра после измененияpublic Guid WorkitemId { get; init; } // Идентификатор задачиpublic string WorkitemKey { get; init; } // Ключ задачиpublic string WorkitemName { get; init; } // Название задачиpublic required string? WorkitemDescription { get; set; } // Описание задачиpublic Guid? WorkitemAssigneeId { get; init; } // Идентификатор ответственного на задачеpublic Guid WorkitemTypeId { get; init; } // Идентификатор типа задачиpublic required DateTime WorkitemCreationDate { get; set; } // Дата создания задачиpublic required Guid? WorkitemWorkflowId { get; init; } // Идентификатор рабочего процесса задачиpublic Guid WorkitemParentId { get; init; } // Идентификатор родительского элемента (задачи или папки)public Guid? WorkitemStatusId { get; init; } // Идентификатор статусаpublic Guid WorkitemCreatedBy { get; set; } // Идентификатор пользователя, который создал задачуpublic Guid WorkitemUpdatedBy { get; set; } // Идентификатор пользователя, который последний изменил задачуpublic DateTime WorkitemUpdateDate { get; set; } // Дата изменения задачиpublic DateTime? WorkitemDueDate { get; set; } // Дата выполненияpublic DateTime? WorkitemEndDate { get; set; } // Дата завершенияpublic DateTime? WorkitemStartDate { get; set; } // Дата началаpublic Dictionary<Guid, object?> WorkitemAttributesValues { get; set; } = new(); // Значения пользовательских атрибутовpublic OkrProgressType? WorkitemProgressType { get; set; }public string? WorkitemProgressData { get; set; }public int? WorkitemProgressValue { get; set; }public int? WorkitemEstimatedTime { get; set; } // Оценка в часахpublic int? WorkitemSpentTime { get; set; } // Сумма затраченного времениpublic int? WorkitemLeftTime { get; set; } // Оставшееся времяpublic int? WorkitemEstimatedStoryPoints { get; set; } // Оценка в сторипоинтахpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Соответствие типа объекта в полях NewValue и OldValue в зависимости от типа события приведено в таблице:
Событие | Тип объекта | Описание объекта |
|---|---|---|
Изменение родительской задачи или папки |
| Идентификатор задачи или папки |
Изменение типа задачи |
| Идентификатор типа |
Изменение процесса |
| Идентификатор процесса |
Изменение статуса |
| Идентификатор статуса |
Изменение имени |
| Название задачи |
Изменение описания |
| Описание задачи |
Изменение ответственного |
| Идентификатор ответственного |
Изменение даты начала |
| Дата начала |
Изменение даты выполнения |
| Дата выполнения |
Изменение оценки в часах |
| Оценка в секундах |
Изменение оценки в сторипоинтах |
| Оценка в сторипоинтах |
Изменение спринта |
| Идентификатор спринта |
Изменение значения прогресса |
| Значение прогресса в % |
Изменение пользовательского атрибута "Число" |
| Числовое значение атрибута |
Изменение пользовательского атрибута "Строка" |
| Строковое значение атрибута |
Изменение пользовательского атрибута "Выбор из списка" |
| Значение опции атрибута |
Изменение пользовательского атрибута "Тег" |
| Значение опции атрибута |
Изменение пользовательского атрибута "Пользователь" |
| Идентификатор пользователя |
Изменение пользовательского атрибута "Дата" |
| Значение даты атрибута |
Изменение пользовательского атрибута "Время" |
| Значение времени в секундах |
Когда триггером автоматизации является событие *Добавление списания времени", передаются следующие данные события:
public class TimeTrackingCreatedEventContext : EventContext{public Guid WorkitemId { get; set; } // Идентификатор задачи по которой добавлено списаниеpublic Guid EntryId { get; set; } // Идентификатор списанияpublic DateTime CreationDate { get; set; } // Дата добавления списанияpublic DateTime StartDate { get; set; } // Дата списанияpublic int Duration { get; set; } // Время списания в секундахpublic string? Description { get; set; } // Описание списанияpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Когда триггером автоматизации является событие "Редактирование списания времени" передаются следующие данные события:
public class TimeTrackingUpdatedEventContext : EventContext{public Guid WorkitemId { get; set; } // Идентификатор задачи по которой добавлено списаниеpublic Guid EntryId { get; set; } // Идентификатор списанияpublic DateTime CreationDate { get; set; } // Дата добавления списанияpublic DateTime StartDate { get; set; } // Дата списанияpublic int Duration { get; set; } // Время списания в секундахpublic string? Description { get; set; } // Описание списанияpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Когда триггером автоматизации является событие Добавление задачи в элемент портфеля, передаются следующие данные события:
public class WorkitemAddedToPortfolioElementEventContext : EventContext{public Guid WorkitemId { get; set; } // Идентификатор задачи, добавленной в элемент портфеляpublic Guid PortfolioElementId { get; set; } // Идентификатор элемента портфеляpublic string PortfolioElementName { get; set; } = default!; // Название элемента портфеляpublic Guid? PortfolioElementStatusId { get; set; } // Идентификатор статуса элемента портфеляpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Когда триггером автоматизации является событие Удаление задачи из элемента портфеля передаются следующие данные события:
public class WorkitemDeletedFromPortfolioElementEventContext : EventContext{public Guid WorkitemId { get; set; } // Идентификатор задачи, добавленной в элемент портфеляpublic Guid PortfolioElementId { get; set; } // Идентификатор элемента портфеляpublic string PortfolioElementName { get; set; } = default!; // Название элемента портфеляpublic Guid? PortfolioElementStatusId { get; set; } // Идентификатор статуса элемента портфеляpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Когда триггером автоматизации является событие Создание спринта, передаются следующие данные события:
public class SprintCreatedEventContext : EventContext{public Guid ExtensionId { get; set; } // Идентификатор расширения Agilepublic Guid SprintId { get; set; } // Идентификатор спринтаpublic string SprintName { get; set; } // Название спринтаpublic SprintStatus SprintStatus { get; set; } // Статус спринтаpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Когда триггером автоматизации является событие Изменение статуса спринта, передаются следующие данные события:
public class SprintUpdatedEventContext : EventContext{public Guid ExtensionId { get; set; } // Идентификатор расширения Agilepublic Guid SprintId { get; set; } // Идентификатор спринтаpublic string SprintName { get; set; } // Название спринтаpublic SprintStatus SprintStatus { get; set; } // Статус спринтаpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Когда триггером автоматизации являются события Создание страницы, Блокирование страницы, Разблокирование страницы передаются следующие данные события:
public class DocumentCreatedEventContext : BaseDocumentEventContext{public Guid DocumentId { get; init; } // Идентификатор страницыpublic required string DocumentKey { get; init; } // Ключ страницыpublic required string DocumentName { get; init; } // Название страницыpublic string? Content { get; init; } // Содержимое страницыpublic int Version { get; init; } // Номер версии страницыpublic required DateTime CreationDate { get; set; } // Дата создания страницфpublic required string DocumentUrl { get; init; } // Ссылка на страницуpublic required string VersionUrl { get; init; } // Ссылка на версию страницыpublic List<Guid>? MentionedUserIds { get; init; } // Идентификаторы пользователей, упомянутых на страницеpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Событиями изменения страницы являются:
- Изменение названия страницы;
- Изменение содержания страницы;
- Изменение статуса страницы;
- Изменение меток страницы;
Для этих событий передаются следующие данные контекста:
public class DocumentUpdatedEventContext : BaseDocumentEventContext{public DateTime UpdateDate { get; set; } // Время изменения страницыpublic object? OldValue { get; init; } // Значение параметра до измененияpublic object? NewValue { get; init; } // Значение параметра после измененияpublic Guid DocumentId { get; init; } // Идентификатор страницыpublic required string DocumentKey { get; init; } // Ключ страницыpublic required string DocumentName { get; init; } // Название страницыpublic string? Content { get; init; } // Содержимое страницыpublic int Version { get; init; } // Номер версии страницыpublic required DateTime CreationDate { get; set; } // Дата создания страницфpublic required string DocumentUrl { get; init; } // Ссылка на страницуpublic required string VersionUrl { get; init; } // Ссылка на версию страницыpublic List<Guid>? MentionedUserIds { get; init; } // Идентификаторы пользователей, упомянутых на страницеpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Соответствие типа объекта в полях NewValue и OldValue в зависимости от типа события приведено в таблице:
Событие | Тип объекта | Описание объекта |
|---|---|---|
Изменение названия страницы |
| Название страницы |
Изменение содержания страницы |
| Содержимое страницы |
Изменение статуса страницы |
| Идентификатор статуса |
Изменение меток страницы |
| Список названий меток |
Когда триггером автоматизации является событие Удаление страницы, передаются следующие данные события:
public class DocumentDeletedEventContext : BaseDocumentEventContext{public Guid DocumentId { get; init; } // Идентификатор страницыpublic Guid? TenantId { get; init; } // Идентификатор тенантаpublic Guid EventId { get; init; } // Идентификатор событияpublic EventTypes EventType { get; init; } // Тип событияpublic string EventName { get; init; } // Название событияpublic Guid UserId { get; init; } // Идентификатор пользователя, инициировавшего событиеpublic Guid WorkspaceId { get; init; } // Идентификатор пространства, в котором произошло событиеpublic string WorkspaceKey { get; init; } // Ключ пространства, в котором произошло событие}
Метод, в котором выполняется пользовательский код, технически находится в классе, наследуемом от базового класса,
имеющим веб-клиент CwmPublicAPI и набор методов.
Примеры использования функций приведены в подразделе Примеры.
Сигнатуры методов имеют своими аргументами идентификаторы или имена/ключи задач, пространств, папок и т.д., там где это применимо, но они, как правило, необязательные. Если что-либо пропущено, то подразумевается текущее пространство, текущая задача и т.п., а для удобства использования они перечислены в порядке возрастания иерархии:
GetWorkitem(string? workitemKey = null, string? workspaceKey = null);
Task<List<WorkspaceModel>?> GetWorkspaces()Task<WorkspaceModel?> GetWorkspace(Guid workspaceId)Task<WorkspaceModel?> GetWorkspace(string workspaceKey = null)Task<WorkspaceModel> CreateWorkspace(string name, string key, string? description = null)Task<WorkspaceModel> UpdateWorkspaceName(string name, string? workspaceKey = null)Task DeleteWorkspace(string? workspaceKey = null)
Task<List<RoleModel>?> GetRoles(string? workspaceKey = null)Task<List<RoleModel>?> GetRoles(bool? isSystem, string? workspaceKey = null)Task<RoleModel?> GetRole(Guid roleId, string? workspaceKey = null)Task<RoleModel?> GetRole(string role, string? workspaceKey = null)Task<RoleModel> CreateRole(string name, List<Permission?>? permissions, string? workspaceKey = null)Task<RoleModel> UpdateRolePermissions(Guid roleId, List<Permission?>? permissions = null, string? workspaceKey = null)
Task<List<ProviderModel>?> GetProviders()Task<List<UserModel>?> GetUsers()Task<UserModel?> GetUser(Guid userId)Task<UserModel?> GetUser(string userName, Guid? providerId = null)Task<List<GroupModel>?> GetUsersGroups(string userName)Task<List<UserModel>?> GetUsersByRole(Guid roleId, string? workspaceKey = null)Task<List<UserModel>?> GetUsersByRole(string roleDisplayName, string? workspaceKey = null)Task AddUserRole(Guid userId, Guid roleId, string? workspaceKey = null)Task DeleteUserRole(Guid userId, Guid roleId, string? workspaceKey = null)
Task<List<GroupModel>?> GetUsersGroups()Task<GroupModel?> GetUserGroup(Guid userGroupId)Task<GroupModel?> GetUserGroup(string name, Guid? providerId = null)Task DeleteGroupRole(Guid groupId, Guid roleId, string? workspaceKey = null)
Task<List<FolderModel>?> GetFolders(string? workspaceKey = null)Task<List<FolderModel>?> GetFolderByParent(Guid parentId, string? workspaceKey = null)Task<FolderModel?> GetFolder(Guid folderId, string? workspaceKey = null)Task<FolderModel?> GetFolder(string name, string? workspaceKey = null)Task<FolderModel> CreateFolder(string name, Guid? parentId = null, string? workspaceKey = null)Task<FolderModel?> UpdateFolder(PatchFolderRequestBody body, Guid folderId, string? workspaceKey = null) // общего вида - сразу все свойства скопомTask<WorkitemModel> UpdateFolderName(string name, Guid folderId, string? workspaceKey = null)Task DeleteFolder(Guid folderId, string? workspaceKey = null)
Task<List<TypeModel>?> GetTypes(string? workspaceKey = null)Task<TypeModel?> GetType(Guid typeId, string? workspaceKey = null)Task<TypeModel?> GetType(string typeName, string? workspaceKey = null)Task<TypeModel> CreateType(CreateTypeRequestBody body, string? workspaceKey = null)Task DeleteType(Guid typeId, string? workspaceKey = null)Task DeleteType(string? type, string? workspaceKey = null)
Task<List<StatusCategoryModel>?> GetStatusCategories()Task<List<StatusModel>?> GetStatuses(string? workspaceKey = null)Task<StatusModel?> GetStatus(Guid statusId, string? workspaceKey = null)Task<StatusModel?> GetStatus(string name, string? workspaceKey = null)Task<StatusModel> CreateStatus(CreateStatusRequestBody body, string? workspaceKey = null)
Task<List<AttributeModel>?> GetAttributes(string? workspaceKey = null)Task<AttributeModel?> GetAttribute(Guid attributeId, string? workspaceKey = null)Task<AttributeModel?> GetAttribute(string attributeName, string? workspaceKey = null)Task<AttributeModel> CreateNumberAttribute(string name, string? description, string? workspaceKey = null)Task<AttributeModel> CreateUniStringAttribute(string name, string? description = null, string? workspaceKey = null)Task<AttributeModel> CreateUserAttribute(string name, string? description = null, string? workspaceKey = null)Task<AttributeModel> CreateDateAttribute(string name, string? description = null, string? workspaceKey = null)Task<AttributeModel> CreateTimeAttribute( string name, string? description = null, string? workspaceKey = null)Task<AttributeModel> CreateUniSelectAttribute(string name, IEnumerable<string> listOptions, string? description = null, string? workspaceKey = null)Task<AttributeModel> CreateTagAttribute(string name, LIEnumerablest<string> listOptions, string? description = null, string? workspaceKey = null)Task<AttributeModel> UpdateWorkitemAttribute(Guid attributeId, PatchAttributeRequestBody body, string? workspaceKey = null)Task<AttributeModel> UpdateScalarWorkitemAttribute(Guid attributeId, string name, string? description = null, string? workspaceKey = null) // Все скалярныеTask<AttributeModel> UpdateListWorkitemAttribute(Guid attributeId, string name, List<PatchAttributeOptionModel> listOptions, string? description = null, string? workspaceKey = null) // UniSelect & TagTask DeleteAttribute(Guid attributeId, string? workspaceKey = null)
Task<List<WorkitemModel>?> GetWorkitems(string? workspaceKey = null)Task<WorkitemModel?> GetWorkitem(Guid workitemId, string? workspaceKey = null)Task<WorkitemModel?> GetWorkitem(string? workitemKey = null, string? workspaceKey = null)Task<List<WorkitemModel>?> GetWorkitemsByParent(bool withSubitems = false, string? parentKey = null, string? workspaceKey = null) // планарный список для иерархии потомков (withSubitems = true)Task<WorkitemModelTree?> GetWorkitemTree(Guid? parentId = null, string? workspaceKey = null)Task<WorkitemModel> CreateWorkitem(CreateWorkitemRequestBody body, string? workspaceKey = null)Task<WorkitemModel?> UpdateWorkitem(PatchWorkitemRequestBody body, string? workitemKey = null, string? workspaceKey = null) // общего видаTask<WorkitemModel> UpdateWorkitemParent(Guid? parentId, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemStatus(string status, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemType(string typeName, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemName(string name, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemDescription(string desc, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemAssignee(Guid userId, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemAssignee(string? userName, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemStartDate(DateTime? startDate, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemDueDate(DateTime? dueDate, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemSprint(Guid? sprintId, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemStoryPoints(int? points, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemOriginalEstimate(int? estimate, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemWorkflow(Guid? workflowId, string? workitemKey = null, string? workspaceKey = null)Task<WorkitemModel> UpdateWorkitemPortfolioElement(List<Guid?>? elementIds, string? workitemKey = null, string? workspaceKey = null)Task<List<SharedWorkitemPermissionModel>> GetWorkitemSharing(string? workitemKey = null, string? workspaceKey = null)Task<SharedWorkitemPermissionModel?> ShareWorkitemForUser(SharedItemAccessLevel accessLevel, Guid userId, string? workitemKey = null, string? workspaceKey = null)Task<SharedWorkitemPermissionModel?> ShareWorkitemForGroup(SharedItemAccessLevel accessLevel, Guid groupId, string? workitemKey = null, string? workspaceKey = null)Task<SharedWorkitemPermissionModel?> UpdateWorkitemSharing(Guid permissionId, SharedItemAccessLevel accessLevel, string? workitemKey = null, string? workspaceKey = null)Task DeleteWorkitemSharing(Guid permissionId, string? workitemKey = null, string? workspaceKey = null)Task DeleteWorkitem(string? workitemKey = null, string? workspaceKey = null)
Task<NumberFieldValueModel?> GetNumberAttributeValue(Guid attributeId, string? workitemKey = null, string? workspaceKey = null)Task<NumberFieldValueModel?> GetNumberAttributeValue(string attributeName, string? workitemKey = null, string? workspaceKey = null)Task<NumberFieldValueModel?> UpdateNumberAttributeValue(string attributeName, double? value, string? workitemKey = null, string? workspaceKey = null)Task<NumberFieldValueModel?> UpdateNumberAttributeValue(Guid attributeId, double? value, string? workitemKey = null, string? workspaceKey = null)
Task<UniStringFieldValueModel?> GetUniStringAttributeValue(Guid attributeId, string? workitemKey = null, string? workspaceKey = null)Task<UniStringFieldValueModel?> GetUniStringAttributeValue(string attributeName, string? workitemKey = null, string? workspaceKey = null)Task<UniStringFieldValueModel?> UpdateUniStringAttributeValue(string attributeName, string value, string? workitemKey = null, string? workspaceKey = null)Task<UniStringFieldValueModel?> UpdateUniStringAttributeValue(Guid attributeId, string value, string? workitemKey = null, string? workspaceKey = null)
Task<UniSelectFieldValueModel?> GetUniSelectAttributeValue(Guid attributeId, string? workitemKey = null, string? workspaceKey = null)Task<UniSelectFieldValueModel?> GetUniSelectAttributeValue(string attributeName, string? workitemKey = null, string? workspaceKey = null)Task<UniSelectFieldValueModel?> UpdateUniSelectAttributeValue(string attributeName, string option, string? workitemKey = null, string? workspaceKey = null)Task<UniSelectFieldValueModel?> UpdateUniSelectAttributeValue(Guid attributeId, string option, string? workitemKey = null, string? workspaceKey = null)
Task<TagFieldValueModel?> GetTagAttributeValue(Guid attributeId, string? workitemKey = null, string? workspaceKey = null)Task<TagFieldValueModel?> GetTagAttributeValue(string attributeName, string? workitemKey = null, string? workspaceKey = null)Task<TagFieldValueModel?> UpdateTagAttributeValue(string attributeName, List<string> options, string? workitemKey = null, string? workspaceKey = null)Task<TagFieldValueModel?> UpdateTagAttributeValue(Guid attributeId, List<string> options, string? workitemKey = null, string? workspaceKey = null)
Task<DateFieldValueModel?> GetDateAttributeValue(Guid attributeId, string? workitemKey = null, string? workspaceKey = null)Task<DateFieldValueModel?> GetDateAttributeValue(string attributeName, string? workitemKey = null, string? workspaceKey = null)Task<DateFieldValueModel?> UpdateDateAttributeValue(string attributeName, DateTime? value, string? workitemKey = null, string? workspaceKey = null)Task<DateFieldValueModel?> UpdateDateAttributeValue(Guid attributeId, DateTime? value, string? workitemKey = null, string? workspaceKey = null)
Task<UserFieldValueModel?> GetUserAttributeValue(Guid attributeId, string? workitemKey = null, string? workspaceKey = null)Task<UserFieldValueModel?> GetUserAttributeValue(string attributeName, string? workitemKey = null, string? workspaceKey = null)Task<UserFieldValueModel?> UpdateUserAttributeValue(string attributeName, Guid userId, string? workitemKey = null, string? workspaceKey = null)Task<UserFieldValueModel?> UpdateUserAttributeValue(Guid attributeId, Guid userId, string? workitemKey = null, string? workspaceKey = null)
Task<TimeFieldValueModel?> GetTimeAttributeValue(Guid attributeId, string? workitemKey = null, string? workspaceKey = null)Task<TimeFieldValueModel?> GetTimeAttributeValue(string attributeName, string? workitemKey = null, string? workspaceKey = null)Task<TimeFieldValueModel?> UpdateTimeAttributeValue(string attributeName, int? seconds, string? workitemKey = null, string? workspaceKey = null)Task<TimeFieldValueModel?> UpdateTimeAttributeValue(Guid attributeId, int? seconds, string? workitemKey = null, string? workspaceKey = null)
Task<List<CommentModel>?> GetWorkitemComments(string? workitemKey = null, string? workspaceKey = null)Task<CommentModel> CreateWorkitemComment(string text, string? workitemKey = null, string? workspaceKey = null)
Task<List<AttachmentModel>?> GetWorkitemAttachments(string? workitemKey = null, string? workspaceKey = null)Task<AttachmentModel?> GetWorkitemAttachment(Guid attachmentId, string? workitemKey = null, string? workspaceKey = null)Task DeleteAttachment(Guid attachmentId, string? workitemKey = null, string? workspaceKey = null)
Task<List<PortfolioModel>?> GetPortfolios(string? workspaceKey = null)Task<List<PortfolioModel>?> GetPortfoliosInFolder(Guid folderId, string? workspaceKey = null)Task<PortfolioModel?> GetPortfolio(Guid portfolioId, string? workspaceKey = null)Task<PortfolioModel?> GetPortfolio(string name, string? workspaceKey = null)Task<PortfolioModel> CreatePortfolio(string name, Guid folderId, string? workspaceKey = null)Task<PortfolioModel> UpdatePortfolio(Guid portfolioId, string name, string? workspaceKey = null)Task DeletePortfolio(Guid portfolioId, string? workspaceKey = null)
Task<List<PortfolioElementModel>?> GetPortfolioElements(string? workspaceKey = null)Task<List<PortfolioElementModel>?> GetPortfolioElementsInFolder(Guid folderId, string? workspaceKey = null)Task<List<PortfolioElementModel>?> GetPortfolioElementsForStatus(string status, string? workspaceKey = null)Task<List<PortfolioElementModel>?> GetPortfolioElements(Guid portfolioId, string? workspaceKey = null)Task<PortfolioElementModel?> GetPortfolioElement(Guid elementId, string? workspaceKey = null)Task<PortfolioElementModel?> GetPortfolioElement(string elementName, string? workspaceKey = null)Task<PortfolioElementModel> CreatePortfolioElement(CreatePortfolioElementRequestBody body, string? workspaceKey = null)Task<PortfolioElementModel> UpdatePortfolioElement(PortfolioElementModel body, string? workspaceKey = null)Task DeletePortfolioElement(Guid elementId, string? workspaceKey = null)
Task<List<WorkitemModel>?> GetWorkitemsByPortfolioElement(Guid elementId, string? workspaceKey = null)
Task<List<AgileModel>?> GetAgileExtensions(string? workspaceKey = null)Task<AgileModel?> GetAgileExtension(Guid agileExtensionId, string? workspaceKey = null)Task<AgileModel> CreateAgile(CreateAgileRequestBody body, string? workspaceKey = null)Task DeleteAgile(Guid agileExtensionId, string? workspaceKey = null)
Task<List<SprintModel>?> GetSprints(string? workspaceKey = null)Task<SprintModel?> GetSprint(Guid sprintId, string? workspaceKey = null)Task<SprintModel?> GetSprint(string name, string? workspaceKey = null)Task<SprintModel> CreateSprint(CreateSprintRequestBody body, string? workspaceKey = null)Task DeleteSprint(Guid sprintId, string? workspaceKey = null)
Task<List<TimeTrackingEntryModel>?> GetTimeTrackingEntries(DateTime? startDate = null, DateTime? endDate = null,List<string>? users = null, int? maxItemsCount = 50, string? fromToken = null)
Task<List<LinkTypeModel>?> GetLinkTypes(string? workspaceKey = null)Task<List<WorkitemLinkModel>?> GetWorkitemLinks(string? workitemKey = null, string? workspaceKey = null)Task<WorkitemLinkModel?> CreateWorkitemLink(string linkedWorkitemKey, string type, string? workitemKey = null, string? workspaceKey = null)Task DeleteWorkitemLink(Guid linkId, string? workitemKey = null, string? workspaceKey = null)Task<List<WorkitemModel>?> GetDocumentLinkedWorkitems(Guid? documentId = null, string? workspaceKey = null)Task<List<DocumentModel>?> GetWorkitemLinkedDocuments(string? workitemKey = null, string? workspaceKey = null)Task AddWorkitemAndDocumentLink(Guid linkedDocumentId, string? documentWorkspaceKey = null, string? workitemKey = null, string? workitemWorkspaceKey = null)Task DeleteWorkitemAndDocumentLink(Guid linkedDocumentId, string? documentWorkspaceKey = null, string? workitemKey = null, string? workitemWorkspaceKey = null)
Task<List<DocumentModel>> GetDocuments(string? workspaceKey = null)Task<DocumentModel> GetDocument(string? documentKey = null, string? workspaceKey = null)Task<List<DocumentStatusModel>?> GetDocumentStatuses(string? workspaceKey = null)Task<DocumentStatusModel?> GetDocumentStatus(Guid statusId, string? workspaceKey = null)Task<DocumentStatusModel?> GetDocumentStatus(string statusName, string? workspaceKey = null)Task<DocumentModel> UpdateDocumentStatus(string status, Guid? documentId = null, string? workspaceKey = null)Task<DocumentModel?> BlockDocument(Guid? documentId = null, string? workspaceKey = null)Task<DocumentModel?> UnblockDocument(Guid? documentId = null, string? workspaceKey = null)Task<List<SharedDocumentPermissionModel>> GetDocumentSharing(string? documentKey = null, string? workspaceKey = null)Task<SharedDocumentPermissionModel> ShareDocumentForUser(SharedItemAccessLevel accessLevel, Guid userId, string? documentKey = null, string? workspaceKey = null)Task<SharedDocumentPermissionModel> ShareDocumentForGroup(SharedItemAccessLevel accessLevel, Guid groupId, string? documentKey = null, string? workspaceKey = null)Task<SharedDocumentPermissionModel?> UpdateDocumentSharing(Guid permissionId, SharedItemAccessLevel accessLevel, string? documentKey = null, string? workspaceKey = null)Task DeleteDocumentSharing(Guid permissionId, string? documentKey = null, string? workspaceKey = null)
Task<string> SendHttpRequest(string url, HttpRequest request) // аргумент request содержит в себе все возможные свойства, передаваемые в следующей функции напрямуюTask<string> SendHttpRequest(string url, HttpMethod method = HttpMethod.Get, object? body = null,List<(string Name, string Value)>? headers = null, string mediaType = "application/json",IReadOnlyDictionary<string, object?>? options = null)
Синтаксис языка — C11, поэтому инициализация коллекций происходит следующим образом: List<int> list = new { 1, 2 }, а не List<int> list = [ 1, 2 ].
Простейший пример скрипта, который даже не использует PublicAPI:
debug("USER = " + e.UserId);
{Name: "Script1",ScriptType: "Method",EventType: "WorkitemNameChanged",Script: "debug(\"USER = \" + e.UserId);", // вот тут в тексте самого скрипта - экранирование кавычек}
var r = new Random();var newName = $"name{r.Next(0, 1000)}";await CreateFolder(newName); // вот тут должно быть awaitdebug("New name = " + newName);
// Сравнение с текущим событием можно будет делать как по его Id, так и по его имени (enum лучше)// Кейс 1: e.EventId == Events.WorkitemCreated (Events - класс с полями в виде именованных guid + некоторые вспомогательные функции)// Кейс 2: e.EventType == EventTypes.WorkitemCreated (EventTypes - enum)// Events также имеет статический словарь '<Guid, EventTypes> Map' - Id и enum события для системных полей// Имена обсуждаемы// Сценарий: автозаполнение исполнителя в зависимости от типа запросаvar wiType = await GetType(e.WorkitemTypeId);if (e.EventType == EventTypes.WorkitemCreated && wiType.Name == "Bug") {// UserModel? assignee = await GetUser("ivan.ivanov"); // в данном случае получение модели излишнеWorkitemModel? workitem = await UpdateWorkitemAssignee("ivan.ivanov");}// Сценарий: по умолчанию проставление среднего приоритета при регистрации запросаvar wiType = await GetType(e.WorkitemTypeId);if (e.EventId == EventTypes.WorkitemCreated && wiType.Name == "Bug") {// если уже имеется Id атрибута, лучше использовать функцию, принимающую именно его, а не имя (производительность)await UpdateUniSelectAttributeValue("Приоритет", "Средний"); // текущий воркайтем//await SetUniSelectAttributeValue(attributeId, "Средний", workitemId2); // сторонний воркайтем, но текущего воркспейса//await SetUniSelectAttributeValue(attributeId, "Средний", workitemId2, workspaceId2); // воркайтем в стороннем воркспейсе}// Сценарий: проставление команды в зависимости от исполнителяvar user = await GetUser(e.WorkitemAssigneeId);// 'WorkitemChanged' нет - все события на изменение гранулярныеif (e.EventType == EventTypes.WorkitemNameChanged && user.Username == "ivan.ivanov") {await UpdateUniSelectAttributeValue("Команда", "Alfa");}// Сценарий: Автоматическое назначение на задачу определенной проектной роли. Как следствие назначается пользователь, у которого установлена такая проектная роль.List<UserModel> users = await GetUsersByRole(roleId); // можно так (все функции планарно на одном уровне, но функции могут быть длиннее по имени - с префиксом сущности)// List<UserModel> users = await WorkspaceUsers.FindByRole(role); // а можно эдак (в АПИ организовать отдельные 'свойства доступа': для текущего воркайтема, общего доступа в воркспейсам, юзерам и т.д.)// Сценарий: Автоматическое присвоение типа документа по вхождению определенного текста в название документа.// Сценарий: Создание задачи с автоматическим определением типа на базе локации пользователя, то есть где пользователь инициировал создание задачи. Чаще всего применимо к спискам (портфелям).WorkitemModel wi = await UpdateWorkitemType("SomeType"); // текущему воркайтему// Сценарий: Расчет и заполнение атрибута в зависимости от значений других атрибутов текущей задачи. Например, автоматическое присваивание задаче портфеля, если она является определенного типа.PortfolioElementModel? elem1 = await GetPortfolioElement(elementId);PortfolioElementModel? elem1 = await GetPortfolioElement("Element1"); // или по elementName// PorfolioElementModel? elem1 = await PorfolioElements.FindByName(name); // либо такelem1.StartDate = DateTimeOffset.UtcNow.AddDays(10).Date; // изменить сам элементawait UpdatePortfolioElement(elem1);await UpdateWorkitemPortfolioElements(elementIds); // привязка к воркайтему списка элементов портфеля - по guid// Сценарий: Установить ответственного при определенных значенияхvar priorityValue = await GetUniSelectAttributeValue(priorityAttributeName);var tagValue = await GetTagAttributeValue(tagAttributeName); // текущий воркайтемif (priorityValue.Value.Name == "Высокий" && tagValue.Value.Any(a => a.Name == "UX")) {await UpdateWorkitemAssignee(userId); // текущему воркайтему!}// Автоматически рассчитать стоимость задачи и записать результат в атрибут "Общая стоимость", перемножив значения атрибутов "Оценка в часах" и "Стоимость часа".NumberFieldValueModel attr1 = await GetNumberAttributeValue("Оценка в часах");NumberFieldValueModel attr2 = await GetNumberAttributeValue("Стоимость часа");if(attr1.Value != null && attr2.Value != null){var val3 = attr1.Value * attr2.Value;await UpdateNumberAttributeValue("Общая стоимость", val3);}// Автоматически рассчитать сумму атрибутов “Оценка” во всех дочерних задачах и заполнить рассчитанным значением атрибута “Оценка“ в родительской задаче.var tree = await GetWorkitemTree();List<WorkitemModel> sons = tree.GetChildren();var result = 0.0;foreach (var son in sons){var attribute = son.Attributes.Single(a => a.NumberFieldValueModel.Name == "Оценка");result += attribute.NumberFieldValueModel.Value ?? 0;}await UpdateNumberAttributeValue("Оценка", result);
Технический писатель: Белова Ирина