Loading…

Star4.1kBook a meeting

Tasks & Statuses

Tasks, the per-team triage queue, statuses, notes, and activity records in the Operation plugin.

Backend code lives under backend/plugins/operation_api/src/modules/{task,status,note,activity}/. The task module also contains the triage model and the task segment definitions in task/meta/segments/.

Task data model

operation_tasks (modules/task/db/definitions/task.ts):

Field Type Notes
name, description string name required
status ObjectId references a team Status; required
teamId ObjectId required; permission scope field
priority, estimatePoint number priority defaults 0; estimatePoint defaults 0
assigneeId, createdBy string Core user ids (indexed, sparse)
labelIds, tagIds string[] Core labels/tags
cycleId, projectId, milestoneId ObjectId optional rollups
startDate, targetDate, statusChangedDate Date statusChangedDate determines "completed" reporting
number, statusType number statusType mirrors the status's type
githubIssueNumber, githubIssueUrl, githubRepoName set by the GitHub sync
propertiesData mixed operation:task property values, keyed by field id
segmentIds string[] written only by the segmentation worker

Task _id is an ObjectId

taskSchema is a plain new Schema(...) without schemaWrapper, so _id stays a Mongo ObjectId. Segment and tRPC code always goes through the Mongoose model so string ids cast correctly. Do not bypass it with a raw driver handle.

Statuses

Status documents are team-scoped ({ name, description, color, type, teamId, order }). type is one of STATUS_TYPES (status/constants/types.ts): STARTED=1, UNSTARTED=2, BACKLOG=3, COMPLETED=4, CANCELLED=5, TRIAGE=6. Creating a team seeds the five default statuses (backlog, todo, in progress, done, cancelled); see status/utils.ts.

Triage queue

Triage items (operation_triage) are inbox work for a team: { name, description, teamId, createdBy, priority, status, number } plus GitHub issue fields. operationConvertTriageToTask creates a task in the same team (optionally looking up status by status type), carries over GitHub linkage, stores the reason as a note on the new task, and deletes the triage record.

operationCancelTriage is not implemented

operationCancelTriage(_id) is declared in the triage GraphQL schema but has no resolver; calling it errors at runtime. To retire a triage item, update its status with operationUpdateTriage or convert it with operationConvertTriageToTask (which deletes the record).

Queries and mutations

Operation Kind Permission
getTasks(filter: ITaskFilter) / getTask(_id) query taskRead
createTask(…) / updateTask(…) / removeTask(_id) mutation taskCreate / taskUpdate / taskRemove
operationGetTriage(_id) / operationGetTriageList(filter) query triageRead
operationAddTriage / operationUpdateTriage mutation triageCreate / triageUpdate
operationConvertTriageToTask(_id, status: Int, reason) mutation triageConvert
getStatus(_id) / getStatusesByType(type, teamId) / getStatusesChoicesByTeam(teamId) query statusRead
addStatus / updateStatus / deleteStatus mutation statusCreate / statusUpdate / statusRemove
getOperationActivities(contentId, …) query taskRead
getNote(_id) / createNote / updateNote / deleteNote query/mutation noteRead / noteCreate / noteUpdate / noteRemove

ITaskFilter accepts status, priority, assigneeId, createdBy, cycleId, projectId, milestoneId, teamId, labelIds, tagIds, estimatePoint, statusType, cycleFilter (noCycle, anyPastCycle, previousCycle, currentCycle, upcomingCycle, anyFutureCycle), projectStatus/projectPriority/projectLeadId, date bounds, and cursor pagination params.

Example createTask call:

mutation {
  createTask(
    name: "Prepare release checklist"
    teamId: "team_1"
    status: "status_todo"
    assigneeId: "user_1"
    priority: 3
    estimatePoint: 5
  ) {
    _id
    name
  }
}

Notes and activity

Note ({ content, contentId, createdBy, mentions, statusId }) attaches to a task or project by contentId; mentions trigger a note notification to the mentioned users, and removeNote is author-only. OperationActivity ({ action, contentId, module, metadata: {newValue, previousValue}, createdBy }) is the audit trail; subscribe to operationActivityChanged(contentId) for live updates.

Subscriptions

operationTaskChanged(_id), operationTaskListChanged(filter: ITaskFilter) (filtered server-side via withFilter), and operationActivityChanged(contentId) publish on create/update through graphqlPubsub.

tRPC

Merged in src/trpc/init-trpc.ts:

Procedure Type Notes
task.tag({ tagIds, targetIds, type, action }) mutation Bulk-set tagIds on tasks
task.findOne({ _ids }) query First task among the ids ({ _id, name, teamId } or null); non-ObjectId ids skipped
task.createFromSource({ userId, doc }) mutation Creates a task as userId; reads teamId from doc.status (must be a status ObjectId); publishes the task subscriptions; returns { _id }

createFromSource is how frontline converts a conversation into a task. It checks no permission; the caller must enforce taskCreate for the acting user.

"Status not found" from createFromSource

doc.status must be a status _id (ObjectId), not a status type number. Only operationConvertTriageToTask accepts a type.

Segments and import/export

  • operation:task.tasks is a segment content type with 19 filterable fields, member listing/counting, materialised segmentIds, and relations user.assignedTasks / user.createdTasks (the field-joined relations rely on the assigneeId/createdBy indexes). The content type must be exactly operation:task.tasks; the event dispatcher keys on it.
  • Import type operation:task.task (taskImportManage) and export types operation:task.task / operation:project.project (taskExportManage / projectExportManage) are registered via meta/import-export. Repeating property groups export as numbered <Group> <n> / <Field> columns.
  • Notifications: taskAssignee (task assigned) and taskStatus (status changed).

Permissions

Modules task, triage, note, status (and project, cycle, milestone, team elsewhere) use scoped permissions: own (records you created), group (records in your teams via scopeField: 'teamId'), all. Read actions are always: true; write actions are grantable. taskAssign is a custom action for assignment control.

Operate on one system.

Talk to our team about consolidating your stack onto erxes. 30-minute walkthrough, custom to your org.