Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions qfieldcloud_sdk/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,3 +736,144 @@ def members_patch(
log(
f'Member "{membership["member"]}" changed role in organization "{membership["organization"]}" to role "{membership["role"]}".'
)


@cli.command(short_help="Get a list of organization teams.")
@click.argument("organization")
@click.pass_context
def teams_list(ctx: Context, organization: str) -> None:
"""Get a list of organization teams."""
teams_list = ctx.obj["client"].get_organization_teams(organization)

if ctx.obj["format_json"]:
print_json(teams_list)
else:
log(f'Teams members in organization "{organization}":')
for object_team in teams_list:
log(f'{object_team["team"]}')


@cli.command(name="teams-create", short_help="Create an organization team.")
@click.argument("organization")
@click.argument("team_name")
@click.pass_context
def teams_create(ctx: Context, organization: str, team_name: str) -> None:
"""Create a new team named TEAM_NAME in ORGANIZATION."""
object_team = ctx.obj["client"].create_organization_team(organization, team_name)

if ctx.obj["format_json"]:
print_json(object_team)
else:
log(f'Team "{object_team["team"]}" created in organization "{organization}".')


@cli.command(name="teams-get", short_help="Get a list of teams on an organization.")
@click.argument("organization")
@click.argument("team_name")
@click.pass_context
def teams_get(ctx: Context, organization: str, team_name: str) -> None:
"""Get details of team TEAM_NAME in ORGANIZATION."""
object_team = ctx.obj["client"].get_organization_team(organization, team_name)

if ctx.obj["format_json"]:
print_json(object_team)
else:
log(
f'Team "{object_team["team"]}" in organization "{object_team["organization"]}":'
)
log(f' Members: {", ".join(object_team["members"])}')


@cli.command(name="teams-patch", short_help="Rename an organization team.")
@click.argument("organization")
@click.argument("team_name")
@click.option("--name", "new_team_name")
@click.pass_context
def teams_patch(
ctx: Context, organization: str, team_name: str, new_team_name: str
) -> None:
"""Rename team TEAM_NAME to NEW_TEAM_NAME in ORGANIZATION."""
object_team = ctx.obj["client"].patch_organization_team(
organization, team_name, new_team_name
)

if ctx.obj["format_json"]:
print_json(object_team)
else:
log(
f'Team "{team_name}" in organization "{organization}" was renamed to "{object_team["team"]}".'
)


@cli.command(name="teams-delete", short_help="Delete an organization team.")
@click.argument("organization")
@click.argument("team_name")
@click.pass_context
def teams_delete(ctx: Context, organization: str, team_name: str) -> None:
"""Delete team TEAM_NAME from ORGANIZATION."""
ctx.obj["client"].delete_organization_team(organization, team_name)

if not ctx.obj["format_json"]:
log(f'Team "{team_name}" was deleted from organization "{organization}".')


@cli.command(
name="team-members-list", short_help="List members of an organization team."
)
@click.argument("organization")
@click.argument("team_name")
@click.pass_context
def team_members_list(ctx: Context, organization: str, team_name: str) -> None:
"""List members of team TEAM_NAME in ORGANIZATION"""
members = ctx.obj["client"].get_organization_team_members(organization, team_name)
if ctx.obj["format_json"]:
print_json(members)
else:
log(f'Members of team "{team_name}" in organization "{organization}":')

for object_member in members:
log(object_member["member"])


@cli.command(
name="team-members-add", short_help="Add a member to an organization team."
)
@click.argument("organization")
@click.argument("team_name")
@click.argument("member_username")
@click.pass_context
def team_members_add(
ctx: Context, organization: str, team_name: str, member_username: str
) -> None:
"""Add member MEMBER_USERNAME to team TEAM_NAME in ORGANIZATION."""
object_member = ctx.obj["client"].add_organization_team_member(
organization, team_name, member_username
)

if ctx.obj["format_json"]:
print_json(object_member)
else:
log(
f'Member "{object_member["member"]}" added to team "{team_name}" in organization "{organization}".'
)


@cli.command(
name="team-members-remove", short_help="Remove a member from an organization team."
)
@click.argument("organization")
@click.argument("team_name")
@click.argument("member_username")
@click.pass_context
def team_members_remove(
ctx: Context, organization: str, team_name: str, member_username: str
) -> None:
"""Remove member MEMBER_USERNAME from team TEAM_NAME in ORGANIZATION."""
ctx.obj["client"].remove_organization_team_member(
organization, team_name, member_username
)

if not ctx.obj["format_json"]:
log(
f'Member "{member_username}" removed from team "{team_name}" in organization "{organization}".'
)
213 changes: 213 additions & 0 deletions qfieldcloud_sdk/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,30 @@ class OrganizationMemberModel(TypedDict):
# updated_at: datetime.datetime


class TeamModel(TypedDict):
"""Represents the structure of a team within an organization in the QFieldCloud system.

Attributes:
team: The team's identifier.
organization: The associated organization identifier.
members: A list of member identifiers belonging to the team.
"""

team: str
organization: str
members: List[str]


class TeamMemberModel(TypedDict):
"""Represents the structure of a team member in the QFieldCloud system.

Attributes:
member: The member's identifier.
"""

member: str


class Pagination:
"""The Pagination class allows for controlling and managing pagination of results within the QFieldCloud SDK.

Expand Down Expand Up @@ -1395,6 +1419,195 @@ def patch_organization_members(

return member

def get_organization_teams(self, organization: str) -> List[TeamModel]:
"""Gets a list of organization teams.

Args:
organization: The name of the organization.

Returns:
A list of TeamModel objects representing the organization's teams.

Example:
```python
teams = client.get_organization_teams(organization="My_Organization_Clan")
for team in teams:
print(team.team)
```
"""
teams = cast(
List[TeamModel],
self._request_json("GET", f"organizations/{organization}/teams/"),
)
return teams

def create_organization_team(self, organization: str, team_name: str) -> TeamModel:
"""Creates a new organization team.

Args:
organization: The name of the organization.
team_name: The name of the new team.

Returns:
A TeamModel object representing the newly created team.

Example:
```python
client.create_organization_team(organization="My_Organization_Clan", team_name="surveyors")
```
"""
team = cast(
TeamModel,
self._request_json(
"POST",
f"organizations/{organization}/teams/",
{"team": team_name},
),
)
return team

def get_organization_team(self, organization: str, team_name: str) -> TeamModel:
"""Gets an organization team by name.

Args:
organization: The name of the organization.
team_name: The name of the team to retrieve.

Returns:
A TeamModel object representing the requested team.

Example:
```python
client.get_organization_team(organization="My_Organization_Clan", team_name="surveyors")
```
"""
team = cast(
TeamModel,
self._request_json(
"GET", f"organizations/{organization}/teams/{team_name}/"
),
)
return team

def patch_organization_team(
self, organization: str, team_name: str, new_team_name: str
) -> TeamModel:
"""Patches an organization team.

Args:
organization: The name of the organization.
team_name: The current name of the team to modify.
new_team_name: The new name for the team.

Returns:
A TeamModel object representing the updated team.

Example:
```python
client.patch_organization_team(organization="My_Organization_Clan", team_name="surveyors", new_team_name="field_surveyors")
```
"""
team = cast(
TeamModel,
self._request_json(
"PUT",
f"organizations/{organization}/teams/{team_name}/",
{
"team": new_team_name,
},
),
)
return team

def delete_organization_team(self, organization: str, team_name: str) -> None:
"""Deletes an organization team.

Args:
organization: The name of the organization.
team_name: The name of the team to delete.

Example:
```python
client.delete_organization_team(organization="My_Organization_Clan", team_name="field_surveyors")
```
"""
self._request("DELETE", f"organizations/{organization}/teams/{team_name}/")

def get_organization_team_members(
self, organization: str, team_name: str
) -> List[TeamMemberModel]:
"""Gets a list of organization team members.

Args:
organization: The name of the organization.
team_name: The name of the team.

Returns:
A list of TeamMemberModel objects representing the team's members.

Example:
```python
members = client.get_organization_team_members(organization="My_Organization_Clan", team_name="admins")
for member in members:
print(member.member)
```
"""
members = cast(
List[TeamMemberModel],
self._request_json(
"GET", f"organizations/{organization}/teams/{team_name}/members/"
),
)
return members

def add_organization_team_member(
self, organization: str, team_name: str, member_username: str
) -> TeamMemberModel:
"""Adds an organization team member.

Args:
organization: The name of the organization.
team_name: The name of the team.
member_username: The username of the member to add.

Returns:
A TeamMemberModel object representing the newly added team member.

Example:
```python
client.add_organization_team_member(organization="My_Organization_Clan", team_name="surveyors", member_username="surveyor_007")
```
"""
member = cast(
TeamMemberModel,
self._request_json(
"POST",
f"organizations/{organization}/teams/{team_name}/members/",
{"member": member_username},
),
)
return member

def remove_organization_team_member(
self, organization: str, team_name: str, member_username: str
) -> None:
"""Removes an organization team member.

Args:
organization: The name of the organization.
team_name: The name of the team.
member_username: The username of the member to remove.

Example:
```python
client.delete_organization_team_member(organization="My_Organization_Clan", team_name="surveyors", member_username="surveyor_007")
```
"""
self._request(
"DELETE",
f"organizations/{organization}/teams/{team_name}/members/{member_username}/",
)

def _request_json(
self,
method: str,
Expand Down