Skip to content

Commit 38bf498

Browse files
committed
Add toggle archived project command
1 parent a7477c2 commit 38bf498

File tree

13 files changed

+206
-52
lines changed

13 files changed

+206
-52
lines changed

cli/trakcli/create/commands/project.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def create_project(
3939
tags = typer.prompt("Tags (CSV format)", default="")
4040
customer = typer.prompt("Customer", default="")
4141
hour_rate = typer.prompt("Hour rate", default=1, show_default=True)
42+
archived = typer.prompt("Archived", default=False, show_default=True)
4243

4344
if project_id:
4445
new_project = Project(
@@ -51,6 +52,7 @@ def create_project(
5152
tags=[t.strip() for t in tags.split(",")] if tags != "" else [],
5253
customer=customer,
5354
rate=hour_rate,
55+
archived=archived,
5456
)
5557

5658
with open(details_path, "w") as details_file:

cli/trakcli/create/commands/work.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from rich import print as rprint
66
from rich.panel import Panel
77

8-
from trakcli.projects.database import get_project_from_config, get_projects_from_config
8+
from trakcli.projects.database import db_get_project_details, get_projects_from_config
99
from trakcli.projects.utils.print_missing_project import print_missing_project
1010
from trakcli.utils.print_with_padding import print_with_padding
1111
from trakcli.works.database import (
@@ -88,7 +88,7 @@ def create_work(
8888
projects_in_config = get_projects_from_config(archived)
8989

9090
if project_id in projects_in_config:
91-
details = get_project_from_config(project_id)
91+
details = db_get_project_details(project_id)
9292

9393
# Check if project esists
9494
if details:

cli/trakcli/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from trakcli.create import app as create_app
1515
from trakcli.dev.commands import app as dev_app
1616
from trakcli.initialize import initialize_trak
17-
from trakcli.projects.commands import app as projects_app
17+
from trakcli.projects import app as projects_app
1818
from trakcli.report import app as report_app
1919
from trakcli.tracker.commands.get_current_session_status import (
2020
get_current_session_status,

cli/trakcli/projects/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import typer
2+
3+
from trakcli.projects.commands.archive import command_project_archive
4+
from trakcli.projects.commands.delete import command_project_delete
5+
from trakcli.projects.commands.list import command_project_list
6+
7+
app = typer.Typer()
8+
9+
10+
app.command(name="list", help="List your projects.")(command_project_list)
11+
app.command(name="delete", help="Delete a project.")(command_project_delete)
12+
app.command(name="archive", help="Archive a project.")(command_project_archive)

cli/trakcli/projects/commands/__init__.py

Whitespace-only changes.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import json
2+
from typing import Annotated, Optional
3+
4+
import questionary
5+
import typer
6+
7+
from trakcli.config.models import Project
8+
from trakcli.projects.database import (
9+
db_get_project_details,
10+
db_get_project_details_path,
11+
get_projects_from_config,
12+
)
13+
from trakcli.projects.messages.print_project_archived_toggle import (
14+
print_project_archived_toggle,
15+
)
16+
from trakcli.projects.messages.print_project_broken_configuration import (
17+
print_project_broken_configuration,
18+
)
19+
from trakcli.projects.utils.print_missing_project import print_missing_project
20+
from trakcli.projects.utils.print_no_projects import print_no_projects
21+
from trakcli.utils.styles_questionary import questionary_style_select
22+
from rich import print as rprint
23+
24+
25+
def command_project_archive(project: Annotated[Optional[str], typer.Argument()] = None):
26+
"""Archive a project."""
27+
28+
projects_in_config = get_projects_from_config(True)
29+
30+
# Check if there are configured projects
31+
if not len(projects_in_config):
32+
print_no_projects()
33+
return
34+
35+
# Provide the list of prjects to the user
36+
if not project:
37+
project = questionary.select(
38+
"Select a project:",
39+
choices=projects_in_config,
40+
pointer="• ",
41+
show_selected=True,
42+
style=questionary_style_select,
43+
).ask()
44+
45+
if not project:
46+
return
47+
48+
# Check if the project exists
49+
if not project or project not in projects_in_config:
50+
print_missing_project(projects_in_config)
51+
return
52+
53+
details_path = db_get_project_details_path(project)
54+
details = db_get_project_details(project)
55+
56+
if details_path and details:
57+
# Toggle the value of archived
58+
details = details._replace(archived=not details.archived)
59+
60+
with open(details_path, "w") as details_file:
61+
json.dump(
62+
details._asdict(),
63+
details_file,
64+
indent=2,
65+
separators=(",", ": "),
66+
)
67+
print_project_archived_toggle(project, details.archived)
68+
else:
69+
print_project_broken_configuration(project)
70+
return
Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,15 @@
11
import pathlib
22
import shutil
3-
from typing import Annotated, Optional
43

54
import typer
65
from rich import print as rprint
76
from rich.panel import Panel
8-
from rich.table import Table
97

10-
from trakcli.config.main import (
11-
TRAK_FOLDER,
12-
)
13-
from trakcli.projects.database import (
14-
get_projects_from_config,
15-
)
8+
from trakcli.config.main import TRAK_FOLDER
169
from trakcli.utils.print_with_padding import print_with_padding
1710

18-
app = typer.Typer()
1911

20-
21-
@app.command(help="List your projects.")
22-
def list(
23-
archived: Annotated[
24-
Optional[bool],
25-
typer.Option(
26-
"--archived",
27-
"-a",
28-
help="Show archived projects in lists.",
29-
),
30-
] = False,
31-
):
32-
"""List the projects."""
33-
34-
projects_in_config = get_projects_from_config(archived)
35-
combined = {*projects_in_config}
36-
37-
number_of_projects = len(combined)
38-
39-
table = Table(
40-
title=f"{number_of_projects} Projects",
41-
)
42-
43-
table.add_column("id", style="green", no_wrap=True)
44-
table.add_column("from", style="cyan", no_wrap=True)
45-
46-
for project in projects_in_config:
47-
table.add_row(project, "config")
48-
49-
rprint("")
50-
rprint(table)
51-
52-
53-
@app.command(help="Delete a project.")
54-
def delete(project_id: str):
12+
def command_project_delete(project_id: str):
5513
"""Delete a project."""
5614

5715
project_path = pathlib.Path(TRAK_FOLDER / "projects" / project_id)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from typing import Annotated, Optional
2+
3+
import typer
4+
from rich import print as rprint
5+
from rich.table import Table
6+
7+
from trakcli.projects.database import get_projects_from_config
8+
9+
10+
def command_project_list(
11+
archived: Annotated[
12+
Optional[bool],
13+
typer.Option(
14+
"--archived",
15+
"-a",
16+
help="Show archived projects in lists.",
17+
),
18+
] = False,
19+
):
20+
"""List the projects."""
21+
22+
projects_in_config = get_projects_from_config(archived)
23+
combined = {*projects_in_config}
24+
25+
number_of_projects = len(combined)
26+
27+
table = Table(
28+
title=f"{number_of_projects} Projects",
29+
)
30+
31+
table.add_column("id", style="green", no_wrap=True)
32+
table.add_column("from", style="cyan", no_wrap=True)
33+
34+
for project in projects_in_config:
35+
table.add_row(project, "config")
36+
37+
rprint("")
38+
rprint(table)

cli/trakcli/projects/database.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
import pathlib
44

55
from trakcli.config.main import TRAK_FOLDER
6+
from trakcli.config.models import Project
7+
8+
from rich import print as rprint
9+
10+
from trakcli.projects.messages.print_project_broken_configuration import (
11+
print_project_broken_configuration,
12+
)
613

714

815
def get_projects_from_db(db_path: Path):
@@ -35,7 +42,7 @@ def get_projects_from_config(archived: bool | None = False):
3542
return projects
3643

3744

38-
def get_project_from_config(project_id: str):
45+
def db_get_project_details(project_id: str) -> Project | None:
3946
"""Get a project in the config by id."""
4047

4148
project_path = pathlib.Path(TRAK_FOLDER / "projects" / project_id)
@@ -44,6 +51,23 @@ def get_project_from_config(project_id: str):
4451
details_path = project_path / "details.json"
4552
with open(details_path, "r") as f:
4653
details = json.load(f)
47-
return details
54+
try:
55+
project = Project(**details)
56+
except Exception:
57+
print_project_broken_configuration(project_id)
58+
return None
59+
60+
return project
61+
else:
62+
return None
63+
64+
65+
def db_get_project_details_path(project_id: str):
66+
"""Get project config path."""
67+
68+
project_path = pathlib.Path(TRAK_FOLDER / "projects" / project_id)
69+
70+
if project_path.exists() and project_path.is_dir():
71+
return project_path / "details.json"
4872
else:
4973
return None
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from rich import print as rprint
2+
from rich.panel import Panel
3+
4+
from trakcli.utils.print_with_padding import print_with_padding
5+
6+
7+
def print_project_archived_toggle(project_id: str, archived: bool):
8+
rprint("")
9+
if archived:
10+
rprint(
11+
Panel.fit(
12+
title=f"[green] The project {project_id} has been archived",
13+
renderable=print_with_padding(
14+
(
15+
"From now on this project won't be accessible from lists.\n\n"
16+
"[orange3]⭐Tip:[/orange3]\n"
17+
f"You can run trak [orange3]project archive {project_id}[/orange3] to unarchive it."
18+
)
19+
),
20+
)
21+
)
22+
else:
23+
rprint(
24+
Panel.fit(
25+
title=f"[green]󱝢 The project {project_id} has been unarchived",
26+
renderable=print_with_padding(
27+
(
28+
"From now on this project will be accessible from lists.\n\n"
29+
"[orange3]⭐Tip:[/orange3]\n"
30+
f"You can run trak [orange3]project archive {project_id}[/orange3] to archive it."
31+
)
32+
),
33+
)
34+
)

0 commit comments

Comments
 (0)