feat: teams within a project

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>
This commit is contained in:
2026-10-15 16:20:35 +02:00
parent 4acf629106
commit 869acd3f1f
41 changed files with 895 additions and 13 deletions

View File

@@ -113,5 +113,11 @@ export function toSettingsInput(
archived: f.archived,
})),
checklistBeforeDone: !!settings.checklistBeforeDone,
teams: (settings.teams ?? []).map((t) => ({
id: t.id,
name: t.name,
memberIds: t.memberIds,
archived: t.archived,
})),
};
}

View File

@@ -60,6 +60,12 @@ fragment ProjectFields on Project {
archived
}
checklistBeforeDone
teams {
id
name
memberIds
archived
}
}
}
@@ -69,6 +75,7 @@ fragment IssueSummaryFields on Issue {
key
type
area
team
title
status
statusCategory

View File

@@ -104,6 +104,8 @@ export type CreateIssueInput = {
/** When work should start (roadmap), YYYY-MM-DD */
startDate?: string | null | undefined;
storyPoints?: number | null | undefined;
/** A team id */
team?: string | null | undefined;
title: string;
/** A ticket type id */
type: string;
@@ -194,6 +196,8 @@ export type IssueFilterInput = {
sort?: IssueSort | null | undefined;
sprintId?: string | null | undefined;
statuses?: Array<string> | null | undefined;
/** Team ids */
teams?: Array<string> | null | undefined;
types?: Array<string> | null | undefined;
unassigned?: boolean | null | undefined;
/** Only tickets not updated since this instant (ISO) */
@@ -279,6 +283,8 @@ export type ProjectSettingsInput = {
customFields?: Array<CustomFieldDefinitionInput> | null | undefined;
issueTypes: Array<IssueTypeOptionInput>;
statuses: Array<WorkflowStatusInput>;
/** Absent: unchanged. Teams cannot be removed: archive them. */
teams?: Array<TeamInput> | null | undefined;
transitions: Array<StatusTransitionsInput>;
};
@@ -339,6 +345,13 @@ export type StatusTransitionsInput = {
to: Array<string>;
};
export type TeamInput = {
archived?: boolean;
id: string;
memberIds?: Array<string>;
name: string;
};
export type UpdateChecklistItemInput = {
done?: boolean | null | undefined;
issueId: string;
@@ -361,6 +374,8 @@ export type UpdateIssueInput = {
/** When work should start (roadmap), YYYY-MM-DD */
startDate?: string | null | undefined;
storyPoints?: number | null | undefined;
/** A team id */
team?: string | null | undefined;
title?: string | null | undefined;
type?: string | null | undefined;
};
@@ -560,6 +575,12 @@ export type ProjectFieldsFragment = {
options: Array<string>;
archived: boolean;
}>;
teams: Array<{
id: string;
name: string;
memberIds: Array<string>;
archived: boolean;
}>;
};
};
@@ -569,6 +590,7 @@ export type IssueSummaryFieldsFragment = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -602,6 +624,7 @@ export type IssueFieldsFragment = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -780,6 +803,7 @@ export type BoardQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -821,6 +845,7 @@ export type IssueQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -886,6 +911,7 @@ export type SearchIssuesQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1059,6 +1085,7 @@ export type MyIssuesQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1096,6 +1123,7 @@ export type IssueChildrenQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1133,6 +1161,7 @@ export type EpicsQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1218,6 +1247,7 @@ export type BacklogQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1289,6 +1319,7 @@ export type TrashQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1325,6 +1356,7 @@ export type DueIssuesQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1364,6 +1396,7 @@ export type IssueListQuery = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -1559,6 +1592,12 @@ export type MyProjectsQuery = {
options: Array<string>;
archived: boolean;
}>;
teams: Array<{
id: string;
name: string;
memberIds: Array<string>;
archived: boolean;
}>;
};
}>;
};
@@ -1611,6 +1650,12 @@ export type ProjectQuery = {
options: Array<string>;
archived: boolean;
}>;
teams: Array<{
id: string;
name: string;
memberIds: Array<string>;
archived: boolean;
}>;
};
};
};
@@ -1773,6 +1818,12 @@ export type PublicProjectsQuery = {
options: Array<string>;
archived: boolean;
}>;
teams: Array<{
id: string;
name: string;
memberIds: Array<string>;
archived: boolean;
}>;
};
}>;
};
@@ -2331,6 +2382,7 @@ export type IssueChangedSubscription = {
key: string;
type: string;
area: string | null;
team: string | null;
title: string;
status: string;
statusCategory: StatusCategory;
@@ -2466,6 +2518,12 @@ export type ProjectChangedSubscription = {
options: Array<string>;
archived: boolean;
}>;
teams: Array<{
id: string;
name: string;
memberIds: Array<string>;
archived: boolean;
}>;
};
};
};
@@ -2521,6 +2579,12 @@ export type MyProjectsChangedSubscription = {
options: Array<string>;
archived: boolean;
}>;
teams: Array<{
id: string;
name: string;
memberIds: Array<string>;
archived: boolean;
}>;
};
};
};
@@ -2909,6 +2973,25 @@ export const ProjectFieldsFragmentDoc = {
kind: 'Field',
name: { kind: 'Name', value: 'checklistBeforeDone' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'teams' },
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'memberIds' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'archived' },
},
],
},
},
],
},
},
@@ -2950,6 +3033,7 @@ export const IssueSummaryFieldsFragmentDoc = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -3209,6 +3293,7 @@ export const IssueFieldsFragmentDoc = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -4986,6 +5071,7 @@ export const BoardDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -5158,6 +5244,7 @@ export const IssueDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -5465,6 +5552,7 @@ export const SearchIssuesDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -6873,6 +6961,7 @@ export const MyIssuesDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -7059,6 +7148,7 @@ export const IssueChildrenDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -7288,6 +7378,7 @@ export const EpicsDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -7796,6 +7887,7 @@ export const BacklogDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -8241,6 +8333,7 @@ export const TrashDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -8427,6 +8520,7 @@ export const DueIssuesDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -8628,6 +8722,7 @@ export const IssueListDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -9655,6 +9750,25 @@ export const MyProjectsDocument = {
kind: 'Field',
name: { kind: 'Name', value: 'checklistBeforeDone' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'teams' },
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'memberIds' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'archived' },
},
],
},
},
],
},
},
@@ -9903,6 +10017,25 @@ export const ProjectDocument = {
kind: 'Field',
name: { kind: 'Name', value: 'checklistBeforeDone' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'teams' },
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'memberIds' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'archived' },
},
],
},
},
],
},
},
@@ -11002,6 +11135,25 @@ export const PublicProjectsDocument = {
kind: 'Field',
name: { kind: 'Name', value: 'checklistBeforeDone' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'teams' },
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'memberIds' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'archived' },
},
],
},
},
],
},
},
@@ -13868,6 +14020,7 @@ export const IssueChangedDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'type' } },
{ kind: 'Field', name: { kind: 'Name', value: 'area' } },
{ kind: 'Field', name: { kind: 'Name', value: 'team' } },
{ kind: 'Field', name: { kind: 'Name', value: 'title' } },
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
{ kind: 'Field', name: { kind: 'Name', value: 'statusCategory' } },
@@ -14529,6 +14682,25 @@ export const ProjectChangedDocument = {
kind: 'Field',
name: { kind: 'Name', value: 'checklistBeforeDone' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'teams' },
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'memberIds' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'archived' },
},
],
},
},
],
},
},
@@ -14764,6 +14936,25 @@ export const MyProjectsChangedDocument = {
kind: 'Field',
name: { kind: 'Name', value: 'checklistBeforeDone' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'teams' },
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'memberIds' },
},
{
kind: 'Field',
name: { kind: 'Name', value: 'archived' },
},
],
},
},
],
},
},