Skip to content

Commit d86beb1

Browse files
committed
Add support for the teams endpoints that were added recently
1 parent 92dd1dd commit d86beb1

File tree

2 files changed

+351
-0
lines changed

2 files changed

+351
-0
lines changed

qfieldcloud_sdk/cli.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,3 +736,143 @@ def members_patch(
736736
log(
737737
f'Member "{membership["member"]}" changed role in organization "{membership["organization"]}" to role "{membership["role"]}".'
738738
)
739+
740+
741+
@cli.command(name="teams-list", short_help="Get a list of organization teams.")
742+
@click.argument("organization")
743+
@click.pass_context
744+
def teams_list(ctx: Context, organization: str) -> None:
745+
"""Get a list of organization teams."""
746+
teams_list = ctx.obj["client"].get_organization_teams(organization)
747+
748+
if ctx.obj["format_json"]:
749+
print_json(teams_list)
750+
else:
751+
log(f'Teams members in organization "{organization}":')
752+
for team in teams_list:
753+
log(f'{team["team"]}')
754+
755+
756+
@cli.command(name="teams-create", short_help="Create an organization team.")
757+
@click.argument("organization")
758+
@click.argument("team_name")
759+
@click.pass_context
760+
def teams_create(ctx: Context, organization: str, team_name: str) -> None:
761+
"""Create a new team named TEAM_NAME in ORGANIZATION."""
762+
team = ctx.obj["client"].create_organization_team(organization, team_name)
763+
764+
if ctx.obj["format_json"]:
765+
print_json(team)
766+
else:
767+
log(f'Team "{team["team"]}" created in organization "{organization}".')
768+
769+
770+
@cli.command(name="teams-get", short_help="Get a list of teams on an organization.")
771+
@click.argument("organization")
772+
@click.argument("team_name")
773+
@click.pass_context
774+
def teams_get(ctx: Context, organization: str, team_name: str) -> None:
775+
"""Get details of team TEAM_NAME in ORGANIZATION."""
776+
team = ctx.obj["client"].get_organization_team(organization, team_name)
777+
778+
if ctx.obj["format_json"]:
779+
print_json(team)
780+
else:
781+
log(f'Team "{team_name}" in organization "{organization}":')
782+
log(f' Name: {team["team"]}')
783+
log(f' Organization: {team["organization"]}')
784+
log(f' Members: {", ".join(team["members"])}')
785+
786+
787+
@cli.command(name="teams-patch", short_help="Rename an organization team.")
788+
@click.argument("organization")
789+
@click.argument("team_name")
790+
@click.argument("new_team_name")
791+
@click.pass_context
792+
def teams_patch(
793+
ctx: Context, organization: str, team_name: str, new_team_name: str
794+
) -> None:
795+
"""Rename team TEAM_NAME to NEW_TEAM_NAME in ORGANIZATION."""
796+
team = ctx.obj["client"].patch_organization_team(
797+
organization, team_name, new_team_name
798+
)
799+
800+
if ctx.obj["format_json"]:
801+
print_json(team)
802+
else:
803+
log(
804+
f'Team "{team_name}" in organization "{organization}" was renamed to "{team["team"]}".'
805+
)
806+
807+
808+
@cli.command(name="teams-delete", short_help="Delete an organization team.")
809+
@click.argument("organization")
810+
@click.argument("team_name")
811+
@click.pass_context
812+
def teams_delete(ctx: Context, organization: str, team_name: str) -> None:
813+
"""Delete team TEAM_NAME from ORGANIZATION."""
814+
ctx.obj["client"].delete_organization_team(organization, team_name)
815+
816+
if not ctx.obj["format_json"]:
817+
log(f'Team "{team_name}" was deleted from organization "{organization}".')
818+
819+
820+
@cli.command(
821+
name="team-members-list", short_help="List members of an organization team."
822+
)
823+
@click.argument("organization")
824+
@click.argument("team_name")
825+
@click.pass_context
826+
def team_members_list(ctx: Context, organization: str, team_name: str) -> None:
827+
"""List members of team TEAM_NAME in ORGANIZATION"""
828+
members = ctx.obj["client"].get_organization_team_members(organization, team_name)
829+
if ctx.obj["format_json"]:
830+
print_json(members)
831+
else:
832+
log(f'Members of team "{team_name}" in organization "{organization}":')
833+
for member in members:
834+
log(member["member"])
835+
836+
837+
@cli.command(
838+
name="team-members-add", short_help="Add a member to an organization team."
839+
)
840+
@click.argument("organization")
841+
@click.argument("team_name")
842+
@click.argument("member_username")
843+
@click.pass_context
844+
def team_members_add(
845+
ctx: Context, organization: str, team_name: str, member_username: str
846+
) -> None:
847+
"""Add member MEMBER_USERNAME to team TEAM_NAME in ORGANIZATION."""
848+
member = ctx.obj["client"].add_organization_team_member(
849+
organization, team_name, member_username
850+
)
851+
852+
if ctx.obj["format_json"]:
853+
print_json(member)
854+
else:
855+
log(
856+
f'Member "{member["member"]}" added to team "{team_name}" in organization "{organization}".'
857+
)
858+
859+
860+
@cli.command(
861+
name="team-members-remove", short_help="Remove a member from an organization team."
862+
)
863+
@click.argument("organization")
864+
@click.argument("team_name")
865+
@click.argument("member_username")
866+
@click.pass_context
867+
def team_members_remove(
868+
ctx: Context, organization: str, team_name: str, member_username: str
869+
) -> None:
870+
"""Remove member MEMBER_USERNAME from team TEAM_NAME in ORGANIZATION."""
871+
ctx.obj["client"].remove_organization_team_member(
872+
organization, team_name, member_username
873+
)
874+
875+
if not ctx.obj["format_json"]:
876+
log(
877+
f'Member "{member_username}" removed from team "{team_name}" in organization "{organization}".'
878+
)

qfieldcloud_sdk/sdk.py

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,30 @@ class OrganizationMemberModel(TypedDict):
154154
# updated_at: datetime.datetime
155155

156156

157+
class TeamModel(TypedDict):
158+
"""Represents the structure of a team within an organization in the QFieldCloud system.
159+
160+
Attributes:
161+
team: The team's identifier.
162+
organization: The associated organization identifier.
163+
members: A list of member identifiers belonging to the team.
164+
"""
165+
166+
team: str
167+
organization: str
168+
members: List[str]
169+
170+
171+
class TeamMemberModel(TypedDict):
172+
"""Represents the structure of a team member in the QFieldCloud system.
173+
174+
Attributes:
175+
member: The member's identifier.
176+
"""
177+
178+
member: str
179+
180+
157181
class Pagination:
158182
"""The Pagination class allows for controlling and managing pagination of results within the QFieldCloud SDK.
159183
@@ -1395,6 +1419,193 @@ def patch_organization_members(
13951419

13961420
return member
13971421

1422+
def get_organization_teams(self, organization: str) -> List[TeamModel]:
1423+
"""Gets a list of organization teams.
1424+
1425+
Args:
1426+
organization: The name of the organization.
1427+
1428+
Returns:
1429+
A list of TeamModel objects representing the organization's teams.
1430+
1431+
Example:
1432+
```python
1433+
teams = client.get_organization_teams(organization="My_Organization_Clan")
1434+
for team in teams:
1435+
print(team.team)
1436+
```
1437+
"""
1438+
teams = cast(
1439+
List[TeamModel],
1440+
self._request_json("GET", f"organizations/{organization}/teams/"),
1441+
)
1442+
return teams
1443+
1444+
def create_organization_team(self, organization: str, team_name: str) -> TeamModel:
1445+
"""Creates a new organization team.
1446+
1447+
Args:
1448+
organization: The name of the organization.
1449+
team_name: The name of the new team.
1450+
1451+
Returns:
1452+
A TeamModel object representing the newly created team.
1453+
1454+
Example:
1455+
```python
1456+
client.create_organization_team(organization="My_Organization_Clan", team_name="surveyors")
1457+
```
1458+
"""
1459+
team = cast(
1460+
TeamModel,
1461+
self._request_json(
1462+
"POST",
1463+
f"organizations/{organization}/teams/",
1464+
{"team": team_name},
1465+
),
1466+
)
1467+
return team
1468+
1469+
def get_organization_team(self, organization: str, team_name: str) -> TeamModel:
1470+
"""Gets an organization team by name.
1471+
1472+
Args:
1473+
organization: The name of the organization.
1474+
team_name: The name of the team to retrieve.
1475+
1476+
Returns:
1477+
A TeamModel object representing the requested team.
1478+
1479+
Example:
1480+
```python
1481+
client.get_organization_team(organization="My_Organization_Clan", team_name="surveyors")
1482+
```
1483+
"""
1484+
team = cast(
1485+
TeamModel,
1486+
self._request_json(
1487+
"GET", f"organizations/{organization}/teams/{team_name}/"
1488+
),
1489+
)
1490+
return team
1491+
1492+
def patch_organization_team(
1493+
self, organization: str, team_name: str, new_team_name: str
1494+
) -> TeamModel:
1495+
"""Patches an organization team.
1496+
1497+
Args:
1498+
organization: The name of the organization.
1499+
team_name: The current name of the team to modify.
1500+
new_team_name: The new name for the team.
1501+
1502+
Returns:
1503+
A TeamModel object representing the updated team.
1504+
1505+
Example:
1506+
```python
1507+
client.patch_organization_team(organization="My_Organization_Clan", team_name="surveyors", new_team_name="field_surveyors")
1508+
```
1509+
"""
1510+
team = cast(
1511+
TeamModel,
1512+
self._request_json(
1513+
"PUT",
1514+
f"organizations/{organization}/teams/{team_name}/",
1515+
{"team": new_team_name},
1516+
),
1517+
)
1518+
return team
1519+
1520+
def delete_organization_team(self, organization: str, team_name: str) -> None:
1521+
"""Deletes an organization team.
1522+
1523+
Args:
1524+
organization: The name of the organization.
1525+
team_name: The name of the team to delete.
1526+
1527+
Example:
1528+
```python
1529+
client.delete_organization_team(organization="My_Organization_Clan", team_name="field_surveyors")
1530+
```
1531+
"""
1532+
self._request("DELETE", f"organizations/{organization}/teams/{team_name}/")
1533+
1534+
def get_organization_team_members(
1535+
self, organization: str, team_name: str
1536+
) -> List[TeamMemberModel]:
1537+
"""Gets a list of organization team members.
1538+
1539+
Args:
1540+
organization: The name of the organization.
1541+
team_name: The name of the team.
1542+
1543+
Returns:
1544+
A list of TeamMemberModel objects representing the team's members.
1545+
1546+
Example:
1547+
```python
1548+
members = client.get_organization_team_members(organization="My_Organization_Clan", team_name="admins")
1549+
for member in members:
1550+
print(member.member)
1551+
```
1552+
"""
1553+
members = cast(
1554+
List[TeamMemberModel],
1555+
self._request_json(
1556+
"GET", f"organizations/{organization}/teams/{team_name}/members/"
1557+
),
1558+
)
1559+
return members
1560+
1561+
def add_organization_team_member(
1562+
self, organization: str, team_name: str, member_username: str
1563+
) -> TeamMemberModel:
1564+
"""Adds an organization team member.
1565+
1566+
Args:
1567+
organization: The name of the organization.
1568+
team_name: The name of the team.
1569+
member_username: The username of the member to add.
1570+
1571+
Returns:
1572+
A TeamMemberModel object representing the newly added team member.
1573+
1574+
Example:
1575+
```python
1576+
client.add_organization_team_member(organization="My_Organization_Clan", team_name="surveyors", member_username="surveyor_007")
1577+
```
1578+
"""
1579+
member = cast(
1580+
TeamMemberModel,
1581+
self._request_json(
1582+
"POST",
1583+
f"organizations/{organization}/teams/{team_name}/members/",
1584+
{"member": member_username},
1585+
),
1586+
)
1587+
return member
1588+
1589+
def remove_organization_team_member(
1590+
self, organization: str, team_name: str, member_username: str
1591+
) -> None:
1592+
"""Removes an organization team member.
1593+
1594+
Args:
1595+
organization: The name of the organization.
1596+
team_name: The name of the team.
1597+
member_username: The username of the member to remove.
1598+
1599+
Example:
1600+
```python
1601+
client.delete_organization_team_member(organization="My_Organization_Clan", team_name="surveyors", member_username="surveyor_007")
1602+
```
1603+
"""
1604+
self._request(
1605+
"DELETE",
1606+
f"organizations/{organization}/teams/{team_name}/members/{member_username}/",
1607+
)
1608+
13981609
def _request_json(
13991610
self,
14001611
method: str,

0 commit comments

Comments
 (0)