feat: leave workspace

This commit is contained in:
Zack Fu Zi Xiang 2024-03-21 01:55:23 +08:00
parent ab9496c248
commit 65491b921f
No known key found for this signature in database
7 changed files with 84 additions and 24 deletions

View File

@ -64,6 +64,12 @@ pub struct Invite {
pub pending_workspace_invitations: Vec<AFWorkspaceInvitation>,
}
#[derive(Template)]
#[template(path = "components/shared_workspaces.html")]
pub struct SharedWorkspaces {
pub shared_workspaces: Vec<AFWorkspace>,
}
#[derive(Template)]
#[template(path = "components/admin_navigate.html")]
pub struct AdminNavigate;

View File

@ -152,7 +152,7 @@ pub async fn invite_accept_handler(
State(state): State<AppState>,
session: UserSession,
Path(invite_id): Path<String>,
) -> Result<WebApiResponse<()>, WebApiError<'static>> {
) -> Result<HeaderMap, WebApiError<'static>> {
accept_workspace_invitation(
&session.token.access_token,
&invite_id,
@ -160,9 +160,7 @@ pub async fn invite_accept_handler(
)
.await?;
Ok(WebApiResponse::<()>::from_str(
"Invitation accepted.\nPlease refresh page to see changes".into(),
))
Ok(htmx_trigger("workspaceInvitationAccepted"))
}
pub async fn change_password_handler(
@ -300,6 +298,12 @@ pub async fn login_refresh_handler(
))
.await?;
verify_token_cloud(
token.access_token.as_str(),
state.appflowy_cloud_url.as_str(),
)
.await?;
let new_session_id = uuid::Uuid::new_v4();
let new_session = session::UserSession::new(new_session_id.to_string(), token);
state.session_store.put_user_session(&new_session).await?;
@ -390,6 +394,12 @@ fn htmx_redirect(url: &str) -> HeaderMap {
h
}
fn htmx_trigger(trigger: &str) -> HeaderMap {
let mut h = HeaderMap::new();
h.insert("HX-Trigger", trigger.parse().unwrap());
h
}
fn new_session_cookie(id: uuid::Uuid) -> Cookie<'static> {
let mut cookie = Cookie::new("session_id", id.to_string());
cookie.set_path("/");

View File

@ -32,8 +32,9 @@ pub fn component_router() -> Router<AppState> {
// User actions
.route("/user/navigate", get(user_navigate_handler))
.route("/user/user", get(user_user_handler))
.route("/user/change_password", get(user_change_password_handler))
.route("/user/change-password", get(user_change_password_handler))
.route("/user/invite", get(user_invite_handler))
.route("/user/shared-workspaces", get(shared_workspaces_handler))
.route("/user/user-usage", get(user_usage_handler))
.route("/user/workspace-usage", get(workspace_usage_handler))
@ -93,14 +94,34 @@ pub async fn admin_navigate_handler() -> Result<Html<String>, WebAppError> {
render_template(templates::AdminNavigate)
}
pub async fn shared_workspaces_handler(
State(state): State<AppState>,
session: UserSession,
) -> Result<Html<String>, WebAppError> {
let user_workspaces =
get_user_workspaces(&session.token.access_token, &state.appflowy_cloud_url).await?;
let profile = get_user_profile(
session.token.access_token.as_str(),
state.appflowy_cloud_url.as_str(),
)
.await?;
let shared_workspaces = user_workspaces
.into_iter()
.filter(|workspace| workspace.owner_uid != profile.uid)
.collect::<Vec<_>>();
render_template(templates::SharedWorkspaces { shared_workspaces })
}
pub async fn user_invite_handler(
State(state): State<AppState>,
session: UserSession,
) -> Result<Html<String>, WebAppError> {
let user_workspaces =
get_user_workspaces(&session.token.access_token, &state.appflowy_cloud_url).await;
get_user_workspaces(&session.token.access_token, &state.appflowy_cloud_url).await?;
let user_workspaces = user_workspaces?;
let profile = get_user_profile(
session.token.access_token.as_str(),
state.appflowy_cloud_url.as_str(),

View File

@ -1,6 +1,6 @@
<div>
<h3>Password Change</h3>
<form hx-post="/web-api/change_password" hx-target="#none">
<form hx-post="/web-api/change-password" hx-target="#none">
<table>
<tr>
<td>New Password:</td>

View File

@ -24,20 +24,13 @@
<br />
<h4>Workspaces shared with you</h4>
<table class="cyan-table table">
<thead>
<tr>
<th>Workspace Name</th>
<th>Owner Name</th>
</tr>
</thead>
{% for shared_workspace in shared_workspaces %}
<tr>
<td> {{ shared_workspace.workspace_name|escape }} </td>
<td> {{ shared_workspace.owner_name|escape }} </td>
</tr>
{% endfor %}
</table>
<div
hx-get="/web/components/user/shared-workspaces"
hx-trigger="workspaceInvitationAccepted from:body"
hx-swap="innerHTML"
>
{% include "shared_workspaces.html" %}
</div>
<br />
<h4>Invite another user to your workspace</h4>
@ -87,7 +80,11 @@
<td> {{ pending_workspace_invitation.workspace_name|default("")|escape }} </td>
<td> {{ pending_workspace_invitation.inviter_email|default("")|escape }} </td>
<td>
<form hx-post="/web-api/invite/{{ pending_workspace_invitation.invite_id|escape }}/accept" hx-target="#none">
<form
hx-post="/web-api/invite/{{ pending_workspace_invitation.invite_id|escape }}/accept"
hx-target="closest tr"
hx-swap="delete"
>
<button class="button cyan" type="submit">Accept</button>
</form>
</td>

View File

@ -0,0 +1,26 @@
<table class="cyan-table table">
<thead>
<tr>
<th>Workspace Name</th>
<th>Owner Name</th>
<th>Action</th>
</tr>
</thead>
{% for shared_workspace in shared_workspaces %}
<tr>
<td> {{ shared_workspace.workspace_name|escape }} </td>
<td> {{ shared_workspace.owner_name|escape }} </td>
<td>
<button
class="button red"
hx-delete="/web-api/workspace/{{ shared_workspace.workspace_id|escape }}/leave"
hx-confirm="Are you sure?"
hx-target="closest tr"
hx-swap="delete"
>
Leave
</button>
</td>
</tr>
{% endfor %}
</table>

View File

@ -9,7 +9,7 @@
<div
class="sidebar-item"
hx-target="#sidebar-content"
hx-get="/web/components/user/change_password"
hx-get="/web/components/user/change-password"
>
Change Password
</div>