AppFlowy-Cloud icon indicating copy to clipboard operation
AppFlowy-Cloud copied to clipboard

chore: create workspace with icon

Open richardshiue opened this issue 7 months ago • 1 comments

Summary by Sourcery

Enable users to assign an optional icon to new workspaces by adding an 'icon' field to the workspace creation flow, persisting it in the database, exposing it via the API, and updating tests accordingly.

New Features:

  • Allow specifying an icon when creating a workspace

Enhancements:

  • Persist a new ‘icon’ column in the database during workspace insertion
  • Propagate the workspace_icon parameter through business logic and DTOs
  • Update the API handler to extract and forward the workspace_icon value

Tests:

  • Extend workspace CRUD tests to include and validate the workspace_icon field

richardshiue avatar May 30 '25 10:05 richardshiue

Reviewer's Guide

Introduces an optional workspace icon by extending the DTO, API handler, service layer, database insertion logic, and tests to accept, store, and validate a new icon field alongside workspace creation.

Sequence Diagram for Workspace Creation with Icon

sequenceDiagram
    actor User
    User->>+API Handler: POST /api/workspace (name, icon?)
    API Handler->>+Workspace Ops: create_workspace_for_user(user_uuid, user_uid, name, icon)
    Workspace Ops->>+Database Service: insert_user_workspace(user_uuid, name, icon, is_initialized)
    Database Service->>+Database: INSERT INTO af_workspace (owner_uid, workspace_name, icon, ...)
    Database-->>-Database Service: AFWorkspaceRow (with icon)
    Database Service-->>-Workspace Ops: AFWorkspaceRow
    Workspace Ops-->>-API Handler: AFWorkspace (with icon)
    API Handler-->>-User: HTTP 200 OK (AFWorkspace)

Entity Relationship Diagram for Workspace with Icon

erDiagram
    USER {
        int user_id PK "User's unique identifier"
        string username
        string email
        string password_hash
        string created_at
        string updated_at
    }

    WORKSPACE {
        int workspace_id PK "Workspace's unique identifier"
        string name
        string icon "New column for workspace icon"
        int owner_id FK "Foreign key to USER"
        string created_at
        string updated_at
    }

    USER ||--o{ WORKSPACE : owns

File-Level Changes

Change Details Files
Pass through a new icon parameter in workspace creation ops
  • Extended create_workspace_for_user signature to accept icon
  • Updated create_empty_workspace to supply empty icon
  • Forwarded workspace_icon to insert_user_workspace in both paths
src/biz/workspace/ops.rs
Store icon column during database insert
  • Added workspace_icon argument to insert_user_workspace signature
  • Modified SQL INSERT to include icon column and bind parameter
libs/database/src/workspace.rs
Expose icon via API handler
  • Extract workspace_icon from incoming JSON with default
  • Adjusted handler call to pass icon into service
src/api/workspace.rs
Extend DTO to include optional icon
  • Added workspace_icon field to CreateWorkspaceParam struct
libs/shared-entity/src/dto/workspace_dto.rs
Update workspace CRUD tests to cover icon
  • Include workspace_icon in test creation payload
  • Assert returned workspace.icon matches expected value
tests/workspace/workspace_crud.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an issue from a review comment by replying to it. You can also reply to a review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull request title to generate a title at any time. You can also comment @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in the pull request body to generate a PR summary at any time exactly where you want it. You can also comment @sourcery-ai summary on the pull request to (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the pull request to resolve all Sourcery comments. Useful if you've already addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull request to dismiss all existing Sourcery reviews. Especially useful if you want to start fresh with a new review - don't forget to comment @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

  • Contact our support team for questions or feedback.
  • Visit our documentation for detailed guides and information.
  • Keep in touch with the Sourcery team by following us on X/Twitter, LinkedIn or GitHub.

sourcery-ai[bot] avatar May 30 '25 10:05 sourcery-ai[bot]

@richardshiue You could use store workspace icon in workspace setting.

#[derive(Serialize, Deserialize)]
pub struct AFWorkspaceSettings {
  #[serde(default)]
  pub disable_search_indexing: bool,

  #[serde(default)]
  pub ai_model: String,
}

using these api endpoints to modify the settings:


impl Client {
  #[instrument(level = "info", skip_all, err)]
  pub async fn get_workspace_settings<T: AsRef<str>>(
    &self,
    workspace_id: T,
  ) -> Result<AFWorkspaceSettings, AppResponseError> {
    let url = format!(
      "{}/api/workspace/{}/settings",
      self.base_url,
      workspace_id.as_ref()
    );
    let resp = self
      .http_client_with_auth(Method::GET, &url)
      .await?
      .send()
      .await?;
    process_response_data::<AFWorkspaceSettings>(resp).await
  }

  #[instrument(level = "info", skip_all, err)]
  pub async fn update_workspace_settings<T: AsRef<str>>(
    &self,
    workspace_id: T,
    changes: &AFWorkspaceSettingsChange,
  ) -> Result<AFWorkspaceSettings, AppResponseError> {
    trace!("workspace settings: {:?}", changes);
    let url = format!(
      "{}/api/workspace/{}/settings",
      self.base_url,
      workspace_id.as_ref()
    );
    let resp = self
      .http_client_with_auth(Method::POST, &url)
      .await?
      .json(&changes)
      .send()
      .await?;
    process_response_data::<AFWorkspaceSettings>(resp).await
  }
}

appflowy avatar Jun 02 '25 04:06 appflowy