Skip to content

Commit

Permalink
feat: UX improvements
Browse files Browse the repository at this point in the history
* fix(agent): return error if socket addr. cannot be parsed from input

* feat(agent): change return type of 'ping' API from string to json

* feat(backend): update return type of agent 'ping' API response

* feat(frontend): updte 'version' and 'latency' display in list view

* chore(backend): add header location in response to update agent request

* chore(frontend): redirect to list view after agent update

* fix(frontend): consistently handle form submit for keyboard and mouse
  • Loading branch information
marekful authored May 15, 2023
1 parent cb72b2c commit 4d33437
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 30 deletions.
15 changes: 6 additions & 9 deletions agent/src/cli/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl Client<'_> {
0
}

pub fn ping(&self) -> i32 {
pub fn ping(&self) -> (String, String) {
// start duration measure
let start = Instant::now();
let sess = self.create_session(None).unwrap();
Expand All @@ -187,16 +187,13 @@ impl Client<'_> {

let result = ch.exit_status().unwrap();
if result != 0 {
return result;
return ("?".to_string(), "?".to_string());
}

println!(
"{:.2}ms / {:.2}ms",
dur_sess.as_millis(),
dur_exec.as_millis()
);

0
(
format!("{:.2}", dur_sess.as_millis()),
format!("{:.2}", dur_exec.as_millis()),
)
}

pub async fn remote_do_copy_async(
Expand Down
7 changes: 6 additions & 1 deletion agent/src/cli/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,12 @@ pub fn command_get_remote_version(client: Client, _: Option<Vec<String>>) {
}

pub fn command_ping(client: Client, _: Option<Vec<String>>) {
client.ping();
let (connect, exec) = client.ping();

println!(
"{{\"connect\": \"{}ms\", \"exec\": \"{}ms\"}}",
connect, exec
);
}

pub fn command_get_local_version(client: Client, _: Option<Vec<String>>) {
Expand Down
27 changes: 24 additions & 3 deletions agent/src/web/miscellaneous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
pub struct VersionResponse {
version: Option<Version>,
error: Option<String>,
latency: Option<String>,
latency: Option<Latency>,
}

#[derive(Deserialize, Serialize, Debug)]
Expand All @@ -27,6 +27,12 @@ pub struct Version {
agent: String,
}

#[derive(Deserialize, Serialize, Debug)]
pub struct Latency {
connect: String,
exec: String,
}

#[derive(Serialize, Debug)]
pub struct PingResponse {
latency: Option<String>,
Expand Down Expand Up @@ -71,7 +77,7 @@ pub async fn version(
let ping_args: Vec<&str> = vec![&agent.host, &agent.port];

// execute 'ping' command
let ping = match run_command_async(91, true, false, COMMAND_PING, ping_args).await {
let ping_str = match run_command_async(91, true, false, COMMAND_PING, ping_args).await {
Ok(ping) => ping,
Err(err) => {
return Json(VersionResponse {
Expand All @@ -97,8 +103,23 @@ pub async fn version(
}
let version: Version = deserialized_result.unwrap();

// parse ping json result
let deserialized_result = serde_json::from_str(&ping_str);
if deserialized_result.is_err() {
return Json(VersionResponse {
version: None,
latency: None,
error: Some(format!(
"parse error: {} -- {}",
deserialized_result.unwrap_err(),
version_str
)),
});
}
let latency: Latency = deserialized_result.unwrap();

Json(VersionResponse {
latency: Some(ping.trim().to_string()),
latency: Some(latency),
version: Some(version),
error: None,
})
Expand Down
14 changes: 12 additions & 2 deletions backend/agents/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type GetTokenUserResponse struct {
}

type GetVersionResponse struct {
Latency string `json:"latency"`
Latency Latency `json:"latency"`
Version Version `json:"version"`
Error string `json:"error"`
}
Expand All @@ -62,6 +62,11 @@ type Version struct {
Files string `json:"files"`
}

type Latency struct {
Connect string `json:"connect"`
Exec string `json:"exec"`
}

type GetResourceResponse struct {
Resource string `json:"resource"`
Error string `json:"error"`
Expand Down Expand Up @@ -378,6 +383,10 @@ func (c *AgentClient) GetVersion(token string) GetVersionResponse {
Agent: "unknown",
Files: "unknown",
}
returnLatency := Latency{
Connect: "?",
Exec: "?",
}
returnError := ""

r, err := nethttps.NewRequest("GET", requestURL, nethttps.NoBody)
Expand Down Expand Up @@ -406,11 +415,12 @@ func (c *AgentClient) GetVersion(token string) GetVersionResponse {
returnError = resp.Error
} else {
returnVersion = resp.Version
returnLatency = resp.Latency
}

return GetVersionResponse{
Version: returnVersion,
Error: returnError,
Latency: resp.Latency,
Latency: returnLatency,
}
}
1 change: 1 addition & 0 deletions backend/http/agents.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ var agentPutHandler = injectAgentWithUser(func(w http.ResponseWriter, r *http.Re
return http.StatusInternalServerError, err
}

w.Header().Set("Location", "/settings/agents")
return http.StatusOK, nil
})

Expand Down
6 changes: 5 additions & 1 deletion frontend/src/api/agents.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@ export async function create(agent) {
}

export async function update(agent, which = ["all"]) {
await fetchURL(`/api/agents/${agent.id}`, {
const res = await fetchURL(`/api/agents/${agent.id}`, {
method: "PUT",
body: JSON.stringify({
what: "agent",
which: which,
data: agent,
}),
});

if (res.status === 200) {
return res.headers.get("Location");
}
}

export async function remoteUserLogin(agentID, name, password) {
Expand Down
24 changes: 14 additions & 10 deletions frontend/src/views/settings/Agent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<errors v-if="error" :errorCode="error.status" />
<div class="row" v-else-if="!loading">
<div class="column">
<form ref="form" class="card">
<form ref="form" @keypress.prevent.enter="submit" class="card">
<div class="card-title">
<h2 v-if="agent.id === 0">
{{ $t("settings.agent.newConnection") }}
Expand All @@ -27,6 +27,7 @@
</button>
<button
v-if="!isNew"
ref="submit"
@click="save"
type="button"
class="button button--flat"
Expand All @@ -37,6 +38,7 @@
</button>
<stateful-button
v-if="isNew"
ref="submit"
:handler="save"
class-name="button button--flat"
label-tr="buttons.connectAndSave"
Expand Down Expand Up @@ -143,6 +145,11 @@ export default {
: this.$showError(e);
}
},
submit(event) {
const submit = this.$refs.submit;
submit && submit.$el && submit.$el.click(event);
submit && submit.click && submit.click(event);
},
async save(event) {
event.preventDefault();
let agent = {
Expand All @@ -151,15 +158,12 @@ export default {
};
try {
if (this.isNew) {
const loc = await api.create(agent);
this.$router.push({ path: loc });
this.$showSuccess(this.$t("settings.agent.connectionCreated"));
} else {
await api.update(agent, ["branding"]);
this.$showSuccess(this.$t("settings.agent.connectionUpdated"));
}
const params = this.isNew ? null : ["branding"];
const method = this.isNew ? "create" : "update";
const message = this.isNew ? "Created" : "Updated";
const loc = await api[method](agent, params);
this.$showSuccess(this.$t(`settings.agent.connection${message}`));
await this.$router.push({ path: loc });
} catch (e) {
this.$showError(e);
}
Expand Down
34 changes: 30 additions & 4 deletions frontend/src/views/settings/Agents.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
<th></th>
</tr>

<tr v-for="agent in agents" :key="agent.id">
<tr v-for="(agent, index) in agents" :key="agent.id">
<td class="status">
<div :class="'status-' + (agent.status || 'loading')">
<i v-if="agent.status === 'online'" class="material-icons">
Expand All @@ -106,14 +106,30 @@
<td>{{ agent.port }}</td>
<td>{{ agent.remote_user.name }}</td>
<td v-if="!agent.error" class="version">
<span v-if="typeof agent.version === 'object'">
{{ agent.version.files }} ({{ agent.version.agent }})
<span
v-if="typeof agent.version === 'object'"
@click="expandVersion(agent, index)"
>
{{ agent.version.files }}
<span v-if="agent.expandVersion === true">
({{ agent.version.agent }})
</span>
</span>
</td>
<td v-else class="version" :colspan="agent.error ? '2' : ''">
<div class="error">{{ agent.error }}</div>
</td>
<td v-if="!agent.error">{{ agent.latency }}</td>
<td v-if="!agent.error">
<span
v-if="typeof agent.latency === 'object'"
@click="expandLatency(agent, index)"
>
{{ agent.latency.connect }}
<span v-if="agent.expandLatency === true">
({{ agent.latency.exec }})
</span>
</span>
</td>
<td class="small">
<router-link :to="'/settings/agents/' + agent.id"
><i class="material-icons">mode_edit</i></router-link
Expand Down Expand Up @@ -177,6 +193,8 @@ export default {
a.latency = v.latency;
a.version = v.version;
a.status = "online";
a.expandVersion = false;
a.expandLatency = false;
if (v.error) {
a.error = v.error;
a.status = "error";
Expand All @@ -195,6 +213,14 @@ export default {
this.tokensCopied.push(false);
});
},
expandVersion(agent, index) {
agent.expandVersion = !agent.expandVersion;
this.agents.splice(index, 1, agent);
},
expandLatency(agent, index) {
agent.expandLatency = !agent.expandLatency;
this.agents.splice(index, 1, agent);
},
copy(event) {
const id = parseInt(event.target.dataset.id);
this.$refs.token[id].select();
Expand Down

0 comments on commit 4d33437

Please sign in to comment.