smbcloud_cli/project/
crud_read.rs

1use std::{fs::OpenOptions, io::Write};
2
3use crate::token::get_smb_token;
4use crate::{
5    cli::CommandResult,
6    ui::{fail_message, fail_symbol, succeed_message, succeed_symbol},
7};
8use anyhow::{anyhow, Result};
9use log::debug;
10use smbcloud_model::project::{Config, Project};
11use smbcloud_network::environment::Environment;
12use smbcloud_networking_project::crud_project_read::{get_project, get_projects};
13use spinners::Spinner;
14use tabled::{Table, Tabled};
15
16#[derive(Tabled)]
17struct ProjectRow {
18    #[tabled(rename = "ID")]
19    id: i32,
20    #[tabled(rename = "Name")]
21    name: String,
22    #[tabled(rename = "Repository")]
23    repository: String,
24    #[tabled(rename = "Description")]
25    description: String,
26}
27
28#[derive(Tabled)]
29struct ProjectDetailRow {
30    #[tabled(rename = "ID")]
31    id: i32,
32    #[tabled(rename = "Name")]
33    name: String,
34    #[tabled(rename = "Repository")]
35    repository: String,
36    #[tabled(rename = "Description")]
37    description: String,
38    #[tabled(rename = "Created at")]
39    created_at: String,
40    #[tabled(rename = "Updated at")]
41    updated_at: String,
42}
43
44pub async fn process_project_list(env: Environment) -> Result<CommandResult> {
45    let mut spinner = Spinner::new(
46        spinners::Spinners::SimpleDotsScrolling,
47        succeed_message("Loading"),
48    );
49    let token = get_smb_token(env).await?;
50    match get_projects(env, token).await {
51        Ok(projects) => {
52            spinner.stop_and_persist(&succeed_symbol(), succeed_message("Loaded."));
53            let msg = if projects.is_empty() {
54                succeed_message("No projects found.")
55            } else {
56                succeed_message("Showing all projects.")
57            };
58            show_projects(projects);
59            Ok(CommandResult {
60                spinner: Spinner::new(
61                    spinners::Spinners::SimpleDotsScrolling,
62                    succeed_message("Loading"),
63                ),
64                symbol: succeed_symbol(),
65                msg,
66            })
67        }
68        Err(e) => {
69            println!("Error: {e:#?}");
70            Ok(CommandResult {
71                spinner,
72                symbol: fail_symbol(),
73                msg: fail_message("Failed to get all projects."),
74            })
75        }
76    }
77}
78
79pub async fn process_project_show(env: Environment, id: String) -> Result<CommandResult> {
80    let mut spinner = Spinner::new(
81        spinners::Spinners::SimpleDotsScrolling,
82        succeed_message("Loading"),
83    );
84    let access_token = get_smb_token(env).await?;
85    match get_project(env, access_token, id).await {
86        Ok(project) => {
87            spinner.stop_and_persist(&succeed_symbol(), succeed_message("Loaded."));
88            let message = succeed_message(&format!("Showing project {}.", &project.name));
89            show_project_detail(&project);
90            Ok(CommandResult {
91                spinner: Spinner::new(
92                    spinners::Spinners::SimpleDotsScrolling,
93                    succeed_message("Loading"),
94                ),
95                symbol: succeed_symbol(),
96                msg: message,
97            })
98        }
99        Err(e) => {
100            spinner.stop_and_persist(&fail_symbol(), fail_message("Failed."));
101            Err(anyhow!("{e}"))
102        }
103    }
104}
105
106pub(crate) fn show_projects(projects: Vec<Project>) {
107    if projects.is_empty() {
108        return;
109    }
110    let rows: Vec<ProjectRow> = projects
111        .into_iter()
112        .map(|p| ProjectRow {
113            id: p.id,
114            name: p.name,
115            repository: p.repository.unwrap_or("-".to_string()),
116            description: p.description.unwrap_or("-".to_owned()),
117        })
118        .collect();
119    let table = Table::new(rows);
120    println!("{table}");
121}
122
123pub(crate) fn show_project_detail(project: &Project) {
124    let row = ProjectDetailRow {
125        id: project.id,
126        name: project.name.clone(),
127        repository: project.repository.clone().unwrap_or("-".to_owned()),
128        description: project.description.clone().unwrap_or("-".to_owned()),
129        created_at: project.created_at.date_naive().to_string(),
130        updated_at: project.updated_at.date_naive().to_string(),
131    };
132    let table = Table::new(vec![row]);
133    println!("{table}");
134}
135
136pub(crate) async fn process_project_use(env: Environment, id: String) -> Result<CommandResult> {
137    let access_token = get_smb_token(env).await?;
138    let project = get_project(env, access_token, id).await?;
139
140    let config = Config {
141        current_project: Some(project),
142        current_auth_app: None,
143    };
144
145    let spinner = Spinner::new(
146        spinners::Spinners::SimpleDotsScrolling,
147        succeed_message("Loading"),
148    );
149    match home::home_dir() {
150        Some(path) => {
151            debug!("{}", path.to_str().unwrap());
152            let mut file = OpenOptions::new()
153                .create(true)
154                .truncate(true)
155                .write(true)
156                .open([path.to_str().unwrap(), "/.smb/config.json"].join(""))?;
157            let json = serde_json::to_string(&config)?;
158            file.write_all(json.as_bytes())?;
159
160            Ok(CommandResult {
161                spinner,
162                symbol: succeed_symbol(),
163                msg: succeed_message("Use project successful."),
164            })
165        }
166        None => {
167            let error = anyhow!("Failed to get home directory.");
168            Err(error)
169        }
170    }
171}