Projects keep teams of members in their settings (settings.teams; people outside the project are dropped, teams are archived, not removed; absent when saving means unchanged). Tickets go to a team (`team`, also filtered in the list and in MCP search_issues), and a comment mentioning @[Frontend](team-FRONT) tells each of its members. Settings has the teams with their members, the ticket a «Equipo» select, the list a team filter, and «@» offers the teams after the people. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
101 lines
2.6 KiB
TypeScript
101 lines
2.6 KiB
TypeScript
import {
|
|
CustomFieldType,
|
|
ProjectSettings,
|
|
SettingColor,
|
|
StatusCategory,
|
|
TypeIcon,
|
|
} from '@task-stream/api/tracker/domain';
|
|
|
|
/** Settings as the APIs carry them: transitions as a list instead of a map. */
|
|
export interface SettingsPayload {
|
|
statuses: {
|
|
id: string;
|
|
name: string;
|
|
category: StatusCategory;
|
|
color: string;
|
|
requiresReason: boolean;
|
|
archived: boolean;
|
|
wipLimit?: number | null;
|
|
}[];
|
|
transitions: { from: string; to: string[] }[];
|
|
issueTypes: {
|
|
id: string;
|
|
name: string;
|
|
icon: string;
|
|
color: string;
|
|
archived: boolean;
|
|
template?: { description?: string | null; checklist?: string[] } | null;
|
|
}[];
|
|
areas: { id: string; name: string; archived: boolean }[];
|
|
/** Absent when saving: unchanged. */
|
|
teams?: {
|
|
id: string;
|
|
name: string;
|
|
memberIds: string[];
|
|
archived: boolean;
|
|
}[];
|
|
/** Definition of done. Absent when saving: unchanged. */
|
|
checklistBeforeDone?: boolean;
|
|
/** Absent when saving: unchanged. */
|
|
customFields?: {
|
|
id: string;
|
|
name: string;
|
|
type: string;
|
|
options?: string[];
|
|
archived: boolean;
|
|
}[];
|
|
}
|
|
|
|
export function toSettingsPayload(settings: ProjectSettings): SettingsPayload {
|
|
return {
|
|
...settings,
|
|
customFields: settings.customFields ?? [],
|
|
checklistBeforeDone: !!settings.checklistBeforeDone,
|
|
teams: settings.teams ?? [],
|
|
transitions: settings.statuses.map((s) => ({
|
|
from: s.id,
|
|
to: settings.transitions[s.id] ?? [],
|
|
})),
|
|
};
|
|
}
|
|
|
|
/** Colours and icons are checked by the domain (validateProjectSettings). */
|
|
export function fromSettingsPayload(payload: SettingsPayload): ProjectSettings {
|
|
return {
|
|
statuses: payload.statuses.map((s) => ({
|
|
...s,
|
|
color: s.color as SettingColor,
|
|
})),
|
|
transitions: Object.fromEntries(
|
|
payload.transitions.map((t) => [t.from, t.to]),
|
|
),
|
|
issueTypes: payload.issueTypes.map(({ template, ...t }) => ({
|
|
...t,
|
|
icon: t.icon as TypeIcon,
|
|
color: t.color as SettingColor,
|
|
...(template
|
|
? {
|
|
template: {
|
|
description: template.description ?? null,
|
|
checklist: template.checklist ?? [],
|
|
},
|
|
}
|
|
: {}),
|
|
})),
|
|
areas: payload.areas,
|
|
...(payload.teams ? { teams: payload.teams } : {}),
|
|
...(payload.checklistBeforeDone != null
|
|
? { checklistBeforeDone: payload.checklistBeforeDone }
|
|
: {}),
|
|
...(payload.customFields
|
|
? {
|
|
customFields: payload.customFields.map((f) => ({
|
|
...f,
|
|
type: f.type as CustomFieldType,
|
|
options: f.options ?? [],
|
|
})),
|
|
}
|
|
: {}),
|
|
};
|
|
}
|