Skip to content

Commit 7056a5d

Browse files
authored
Merge pull request #75 from opengisch/QF-5206-add_support_for_the_teams_endpoints
Add support for the teams endpoints that were added recently
2 parents 92dd1dd + 8a06b07 commit 7056a5d

2 files changed

Lines changed: 354 additions & 0 deletions

File tree

qfieldcloud_sdk/cli.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,3 +736,144 @@ 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(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 object_team in teams_list:
753+
log(f'{object_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+
object_team = ctx.obj["client"].create_organization_team(organization, team_name)
763+
764+
if ctx.obj["format_json"]:
765+
print_json(object_team)
766+
else:
767+
log(f'Team "{object_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+
object_team = ctx.obj["client"].get_organization_team(organization, team_name)
777+
778+
if ctx.obj["format_json"]:
779+
print_json(object_team)
780+
else:
781+
log(
782+
f'Team "{object_team["team"]}" in organization "{object_team["organization"]}":'
783+
)
784+
log(f' Members: {", ".join(object_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.option("--name", "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+
object_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(object_team)
802+
else:
803+
log(
804+
f'Team "{team_name}" in organization "{organization}" was renamed to "{object_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+
834+
for object_member in members:
835+
log(object_member["member"])
836+
837+
838+
@cli.command(
839+
name="team-members-add", short_help="Add a member to an organization team."
840+
)
841+
@click.argument("organization")
842+
@click.argument("team_name")
843+
@click.argument("member_username")
844+
@click.pass_context
845+
def team_members_add(
846+
ctx: Context, organization: str, team_name: str, member_username: str
847+
) -> None:
848+
"""Add member MEMBER_USERNAME to team TEAM_NAME in ORGANIZATION."""
849+
object_member = ctx.obj["client"].add_organization_team_member(
850+
organization, team_name, member_username
851+
)
852+
853+
if ctx.obj["format_json"]:
854+
print_json(object_member)
855+
else:
856+
log(
857+
f'Member "{object_member["member"]}" added to team "{team_name}" in organization "{organization}".'
858+
)
859+
860+
861+
@cli.command(
862+
name="team-members-remove", short_help="Remove a member from an organization team."
863+
)
864+
@click.argument("organization")
865+
@click.argument("team_name")
866+
@click.argument("member_username")
867+
@click.pass_context
868+
def team_members_remove(
869+
ctx: Context, organization: str, team_name: str, member_username: str
870+
) -> None:
871+
"""Remove member MEMBER_USERNAME from team TEAM_NAME in ORGANIZATION."""
872+
ctx.obj["client"].remove_organization_team_member(
873+
organization, team_name, member_username
874+
)
875+
876+
if not ctx.obj["format_json"]:
877+
log(
878+
f'Member "{member_username}" removed from team "{team_name}" in organization "{organization}".'
879+
)

qfieldcloud_sdk/sdk.py

Lines changed: 213 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,195 @@ 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+
{
1516+
"team": new_team_name,
1517+
},
1518+
),
1519+
)
1520+
return team
1521+
1522+
def delete_organization_team(self, organization: str, team_name: str) -> None:
1523+
"""Deletes an organization team.
1524+
1525+
Args:
1526+
organization: The name of the organization.
1527+
team_name: The name of the team to delete.
1528+
1529+
Example:
1530+
```python
1531+
client.delete_organization_team(organization="My_Organization_Clan", team_name="field_surveyors")
1532+
```
1533+
"""
1534+
self._request("DELETE", f"organizations/{organization}/teams/{team_name}/")
1535+
1536+
def get_organization_team_members(
1537+
self, organization: str, team_name: str
1538+
) -> List[TeamMemberModel]:
1539+
"""Gets a list of organization team members.
1540+
1541+
Args:
1542+
organization: The name of the organization.
1543+
team_name: The name of the team.
1544+
1545+
Returns:
1546+
A list of TeamMemberModel objects representing the team's members.
1547+
1548+
Example:
1549+
```python
1550+
members = client.get_organization_team_members(organization="My_Organization_Clan", team_name="admins")
1551+
for member in members:
1552+
print(member.member)
1553+
```
1554+
"""
1555+
members = cast(
1556+
List[TeamMemberModel],
1557+
self._request_json(
1558+
"GET", f"organizations/{organization}/teams/{team_name}/members/"
1559+
),
1560+
)
1561+
return members
1562+
1563+
def add_organization_team_member(
1564+
self, organization: str, team_name: str, member_username: str
1565+
) -> TeamMemberModel:
1566+
"""Adds an organization team member.
1567+
1568+
Args:
1569+
organization: The name of the organization.
1570+
team_name: The name of the team.
1571+
member_username: The username of the member to add.
1572+
1573+
Returns:
1574+
A TeamMemberModel object representing the newly added team member.
1575+
1576+
Example:
1577+
```python
1578+
client.add_organization_team_member(organization="My_Organization_Clan", team_name="surveyors", member_username="surveyor_007")
1579+
```
1580+
"""
1581+
member = cast(
1582+
TeamMemberModel,
1583+
self._request_json(
1584+
"POST",
1585+
f"organizations/{organization}/teams/{team_name}/members/",
1586+
{"member": member_username},
1587+
),
1588+
)
1589+
return member
1590+
1591+
def remove_organization_team_member(
1592+
self, organization: str, team_name: str, member_username: str
1593+
) -> None:
1594+
"""Removes an organization team member.
1595+
1596+
Args:
1597+
organization: The name of the organization.
1598+
team_name: The name of the team.
1599+
member_username: The username of the member to remove.
1600+
1601+
Example:
1602+
```python
1603+
client.delete_organization_team_member(organization="My_Organization_Clan", team_name="surveyors", member_username="surveyor_007")
1604+
```
1605+
"""
1606+
self._request(
1607+
"DELETE",
1608+
f"organizations/{organization}/teams/{team_name}/members/{member_username}/",
1609+
)
1610+
13981611
def _request_json(
13991612
self,
14001613
method: str,

0 commit comments

Comments
 (0)