Files
oxspeak_server/.junie/plans/add-server-button.md
T
2026-07-27 10:38:22 +02:00

6.4 KiB

sessionId
sessionId
session-260727-093242-giao

Requirements

Overview & Goals

The goal of this task is to add an "Add Server" button and creation functionality to the frontend application, allowing users to create new servers directly from the UI. Backend entrypoints (POST /servers) are already fully implemented in Rust.

Scope

  • In Scope:
    • Update frontend/src/stores/server.ts to include a createServer action communicating with POST /servers.
    • Update frontend/src/layouts/AppLayout.vue to add an "Add Server" button in the left rail navigation drawer alongside existing server avatars.
    • Add a server creation modal dialog (v-dialog) with input fields for server name and optional password.
    • Handle loading states, validation (server name required), error handling, and automatically select or route to the newly created server.
  • Out of Scope:
    • Modifying backend server logic or endpoints (already implemented).
    • Server permission editing UI enhancements (unless directly related to server creation flow).

User Stories

  • As a user, I want to click an "Add Server" button in the sidebar so that I can create a new server.
  • As a user, I want a modal dialog where I can enter the server name and optional password so that my server is properly configured upon creation.
  • As a user, I want the server list in the sidebar to update immediately when a new server is created so that I can switch to it right away.

Functional Requirements

  • Sidebar Button: An intuitive '+' or add icon button rendered in the rail navigation drawer of AppLayout.vue.
  • Creation Dialog: A Vuetify modal dialog (v-dialog) containing:
    • Text field for server name (required).
    • Optional password field (optional).
    • Cancel and Create buttons with loading state handling.
  • Store Integration: useServerStore must provide a createServer action that performs POST /servers with the appropriate payload ({ name, password, is_default }).

Technical Design

Current Implementation

  • Backend: POST /servers is implemented in src/routes/server/handlers.rs and accepts CreateServerRequest (name, password, is_default), returning ServerResponse. Note that it requires Superuser authorization (_admin: Superuser).
  • Frontend Stores: frontend/src/stores/server.ts currently fetches servers via GET /servers into state.servers.
  • Frontend Layout: frontend/src/layouts/AppLayout.vue renders a rail navigation drawer listing existing servers as avatars with router links to /server/${server.id}.

Key Decisions

  • Placement of Add Server Button: Placed at the bottom or top of the server list inside the rail navigation drawer of AppLayout.vue, consistent with Discord-like and existing channel creation patterns (New Channel button in frontend/src/pages/server/index.vue).
  • Dialog Pattern: Reusing the exact modal dialog pattern (v-dialog, v-card, v-text-field, v-btn) already established in frontend/src/pages/server/index.vue for creating channels.

Proposed Changes

  1. Server Store (frontend/src/stores/server.ts):
    • Add createServer action:
      async createServer(payload: { name: string; password?: string | null; is_default?: boolean }) {
        const api = useApi();
        const response = await api.post("/servers", payload);
        if (!response.ok) {
          const error = await response.json();
          throw new Error(error.message || 'Failed to create server');
        }
        const newServer = await response.json();
        this.servers.push(newServer);
        return newServer;
      }
      
  2. AppLayout (frontend/src/layouts/AppLayout.vue):
    • Add a state ref for dialog visibility (showDialog), form data (formData), and submission status (isSubmitting).
    • Add an add server button (v-avatar with icon="mdi-plus" or v-btn) inside the rail drawer.
    • Add v-dialog template with inputs for server name and password.
    • Wire handleSubmit to invoke serverStore.createServer().

File Structure

  • Modified Files:
    • frontend/src/stores/server.ts
    • frontend/src/layouts/AppLayout.vue

Architecture Diagram

graph LR
    User -->|Clicks Add Server| AppLayout
    AppLayout -->|Opens Dialog| Dialog[v-dialog]
    Dialog -->|Submits Form| ServerStore[useServerStore]
    ServerStore -->|POST /servers| Backend[Rust Backend API]
    Backend -->|Created Server| ServerStore
    ServerStore -->|Updates servers list| AppLayout

Testing

Validation Approach

  • Verification: Ensure the Vue application builds successfully with TypeScript and Vite.
  • Manual/UI Verification Scenarios:
    1. Open the application layout (AppLayout.vue).
    2. Click the plus button in the sidebar.
    3. Verify the "Create Server" dialog appears with name and password fields.
    4. Submit a valid server name and verify that a POST request is sent to /servers, the dialog closes, and the new server avatar appears in the sidebar.
    5. Verify validation prevents submission when the server name is empty.

Key Scenarios

  • Successful Creation: Server is successfully created and appended to the sidebar list.
  • Validation Error: Empty server name disables the create button or shows an alert.
  • API Error Handling: Catch and log API failures gracefully.

Delivery Steps

* Step 1: Extend server Pinia store with createServer action

Extend the server Pinia store with createServer action.

  • Update frontend/src/stores/server.ts to include createServer(payload: { name: string; password?: string | null; is_default?: boolean }).
  • Handle error states, API POST requests to /servers, and state updates to push the newly created server to this.servers.

Step 2: Add Add Server UI button and creation dialog to AppLayout

Add 'Add Server' UI button and creation dialog to AppLayout.

  • Update frontend/src/layouts/AppLayout.vue to add a '+' or 'Add Server' button in the rail navigation drawer.
  • Implement a reactive modal dialog (v-dialog) with form fields for server name and optional password.
  • Wire up form submission to call serverStore.createServer(), handle loading state, and close/reset the dialog on success.

Step 3: Verify frontend integration and build

Verify build and test integration.

  • Ensure TypeScript types, Vuetify components, and pinia store integration are correct.
  • Verify frontend compilation without errors.