Skip to content

Commit e9c335c

Browse files
authored
claude agi (#23)
1 parent 9d4e2f2 commit e9c335c

83 files changed

Lines changed: 1265 additions & 916 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ERRORS.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Monkey Test Report
2+
3+
Date: 2025-12-29
4+
5+
## Summary
6+
7+
Tested all pages and interactive elements across the application.
8+
9+
## Issues Found and Fixed
10+
11+
### ~~High Priority~~ ✅ FIXED
12+
13+
#### ~~1. "untitled page" text displayed on all pages~~
14+
15+
- **Location**: Bottom of every page (svelte-announcer accessibility element)
16+
- **Root cause**: No page titles set, causing SvelteKit's screen reader announcer to say "untitled page"
17+
- **Fix**: Added `<svelte:head><title>...</title></svelte:head>` to all pages
18+
19+
### ~~Medium Priority~~ ✅ FIXED
20+
21+
#### ~~2. "Loading messages..." persists in empty channels~~
22+
23+
- **Location**: `apps/desktop/src/components/chat/MessageList.svelte`
24+
- **Root cause**: Condition checked `messagesData.length > 0` instead of checking loading state
25+
- **Fix**: Added proper `isLoading` check from useQuery hook
26+
27+
#### ~~3. Add Member uses browser prompt() dialog~~
28+
29+
- **Location**: `apps/desktop/src/routes/orgs/[orgId]/settings/`
30+
- **Root cause**: Used native `prompt()` and `confirm()` for user input
31+
- **Fix**: Created proper DaisyUI modal in MemberList.svelte
32+
33+
### ~~Low Priority~~ ✅ FIXED
34+
35+
#### ~~4. DM search shows no results indication~~
36+
37+
- **Location**: `apps/desktop/src/components/dms/UserSearch.svelte`
38+
- **Root cause**: No else condition for empty results
39+
- **Fix**: Added "No users found" message when search completes with no results
40+
41+
## Features Tested (All Working)
42+
43+
- [x] Organization selection page
44+
- [x] Organization switching
45+
- [x] Channel navigation (general, test-channel)
46+
- [x] Channel creation modal
47+
- [x] Message input and sending
48+
- [x] Message reactions (add/remove)
49+
- [x] Message menu (Reply, Add Reaction, Show Reactions, Pin, Edit, Delete)
50+
- [x] Message pinning
51+
- [x] Search messages
52+
- [x] Poll creation form
53+
- [x] Emoji picker (all tabs, search, favorites)
54+
- [x] User profile/personalization settings (name change, profile picture)
55+
- [x] Organization settings (edit name/description)
56+
- [x] Organization member list
57+
- [x] New organization creation page
58+
- [x] Signin redirect (when already logged in)
59+
60+
## Files Modified
61+
62+
1. `apps/desktop/src/routes/+page.svelte` - Added page title
63+
2. `apps/desktop/src/routes/signin/+page.svelte` - Added page title
64+
3. `apps/desktop/src/routes/signout/+page.svelte` - Added page title
65+
4. `apps/desktop/src/routes/orgs/new/+page.svelte` - Added page title
66+
5. `apps/desktop/src/routes/orgs/[orgId]/+page.svelte` - Added page title
67+
6. `apps/desktop/src/routes/orgs/[orgId]/settings/+page.svelte` - Added page title, updated onAddMember callback
68+
7. `apps/desktop/src/routes/orgs/[orgId]/personalization/+page.svelte` - Added page title
69+
8. `apps/desktop/src/routes/orgs/[orgId]/chat/[channelId]/+page.svelte` - Added page title
70+
9. `apps/desktop/src/components/chat/MessageList.svelte` - Fixed loading state logic
71+
10. `apps/desktop/src/routes/orgs/[orgId]/settings/MemberList.svelte` - Added modal for Add Member
72+
11. `apps/desktop/src/routes/orgs/[orgId]/settings/member-utils.ts` - Refactored to throw errors instead of using alerts
73+
12. `apps/desktop/src/routes/orgs/[orgId]/settings/settings-controller.svelte.ts` - Updated to accept email parameter
74+
13. `apps/desktop/src/components/dms/UserSearch.svelte` - Added "No users found" message
75+
76+
## Test Environment
77+
78+
- Browser: Chrome (via DevTools MCP)
79+
- URL: http://localhost:5173
80+
- User: Dev User (dev@example.com) - Admin role

TODOS.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# TODOS
2+
3+
Generated: 2025-12-24
4+
5+
## Batch 1: Critical Security Fixes
6+
7+
- [ ] Fix SQL injection in message search (`apps/server/src/domains/messages/service.ts` - escape `ilike` pattern)
8+
- [ ] Add file path sanitization (`apps/server/src/domains/files/service.ts` - prevent `../` traversal)
9+
- [ ] Add WebSocket auth re-validation on subscribe (`apps/server/src/ws/index.ts` - check permissions on subscribe)
10+
- [ ] Add rate limiting middleware (`apps/server/src/middleware/` - create rate-limit.ts)
11+
12+
## Batch 2: High-Impact Performance Fixes
13+
14+
- [ ] Fix N+1 query in message list (`apps/server/src/domains/messages/service.ts` - include reactions/attachments in query)
15+
- [ ] Remove duplicate useQuery per message (`apps/desktop/src/components/MessageItem.svelte` - pass reactions as props)
16+
- [ ] Deduplicate permission checks (`apps/server/src/domains/permissions/service.ts` - cache within request context)
17+
- [ ] Lazy load CodeMirror and emoji-picker (`apps/desktop/src/components/` - use dynamic imports)
18+
19+
## Batch 3: Code Quality & Dead Code Removal
20+
21+
- [ ] Delete unused example/ directory (`.storybook`, `apps/desktop/src/example/`)
22+
- [ ] Remove console.log/error statements (9 files - use proper logger or delete)
23+
- [ ] Split large components: `MessageItem.svelte` (143 lines → ~50 lines each)
24+
- [ ] Split large components: `ChannelList.svelte` (141 lines → ~50 lines each)
25+
26+
## Batch 4: Accessibility Fixes
27+
28+
- [ ] Add aria-labels to icon buttons (`apps/desktop/src/components/` - all IconButton components)
29+
- [ ] Replace alert() with toast notifications (`apps/desktop/src/` - create toast utility)
30+
- [ ] Add form labels for WCAG compliance (`apps/desktop/src/routes/` - all form inputs)
31+
- [ ] Standardize placeholder text language (`apps/desktop/src/` - choose Japanese or English consistently)
32+
33+
## Deferred (Needs User Confirmation)
34+
35+
- [ ] DISABLE_AUTH flag - clarify production usage policy (`apps/server/src/middleware/auth.ts`)
36+
- [ ] Add CSRF protection - confirm if needed for API-only backend (`apps/server/src/middleware/`)
37+
- [ ] Add security headers - confirm headers policy (`apps/server/src/index.ts`)
38+
- [ ] shadow-2xl usage - confirm if Clarity design principles apply (`apps/desktop/src/components/`)
39+
- [ ] Empty state CTAs - requires design decisions (multiple files)
40+
41+
## Rejected (Low Value / Out of Scope)
42+
43+
- Duplicate logic in unread.ts - minimal impact, refactor during feature work
44+
- Test coverage improvements - separate test-focused sprint needed
45+
- Flaky waitForTimeout(500) - address when writing new E2E tests
46+
- Page Object Model - requires significant test refactoring

apps/desktop/src/components/app/ChatApp.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@
5353
{:else}
5454
<div class="flex flex-1 items-center justify-center">
5555
<div class="text-center">
56-
<p class="text-muted text-lg">チャンネルを選択</p>
56+
<p class="text-muted text-lg">Select a Channel</p>
5757
<p class="text-muted mt-1 text-sm opacity-60">
58-
左のサイドバーからチャンネルを選んでください
58+
Choose a channel from the sidebar
5959
</p>
6060
</div>
6161
</div>

apps/desktop/src/components/app/OrganizationSidebar.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,25 @@
1616
<aside class="border-subtle bg-base-200 flex h-full w-72 flex-col border-r">
1717
<!-- Organization header -->
1818
<header
19-
class="border-subtle flex items-center justify-between border-b px-4 py-3"
19+
class="border-subtle flex items-center justify-between border-b px-4 py-4"
2020
>
2121
<div class="min-w-0 flex-1">
2222
<h1 class="truncate font-semibold tracking-tight">
2323
{organization?.name ?? "Loading..."}
2424
</h1>
2525
</div>
26-
<div class="flex items-center gap-1">
26+
<div class="flex items-center gap-2">
2727
<a
2828
href="/orgs/{organizationId}/settings"
2929
class="btn btn-ghost btn-sm btn-square hover-highlight"
30-
title="組織設定"
30+
title="Organization Settings"
3131
>
3232
<Settings class="text-muted size-4" />
3333
</a>
3434
<a
3535
href="/"
3636
class="btn btn-ghost btn-sm btn-square hover-highlight"
37-
title="組織を切り替え"
37+
title="Switch Organization"
3838
>
3939
<ArrowLeftRight class="text-muted size-4" />
4040
</a>

apps/desktop/src/components/channels/Channel.svelte

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,24 @@
1818
() => selectedChannelId,
1919
() => organizationId,
2020
);
21+
22+
function autofocus(node: HTMLElement) {
23+
node.focus();
24+
}
2125
</script>
2226

2327
<div class="flex h-full flex-col">
2428
<!-- Channel header -->
2529
<header
2630
class="border-subtle flex items-center justify-between border-b px-6 py-4"
2731
>
28-
<div class="flex items-center gap-3">
29-
<Hash class="size-5 opacity-50" />
32+
<div class="flex items-center gap-4">
33+
<Hash class="size-5 opacity-60" />
3034
<h1 class="text-base font-semibold">
3135
{controller.selectedChannel.data?.name ?? "..."}
3236
</h1>
3337
{#if controller.selectedChannel.data?.description}
34-
<span class="hidden text-sm opacity-40 sm:inline">
38+
<span class="hidden text-sm opacity-60 sm:inline">
3539
— {controller.selectedChannel.data.description}
3640
</span>
3741
{/if}
@@ -44,10 +48,11 @@
4448
>
4549
<input
4650
type="text"
47-
placeholder="メッセージを検索..."
48-
class="input input-sm input-bordered bg-base-200 w-56 pr-8 text-sm transition-all duration-150 focus:w-64"
51+
placeholder="Search messages..."
52+
class="input input-sm input-bordered bg-base-200 w-56 pr-8 text-sm transition-all duration-200 focus:w-64"
4953
bind:value={controller.searchQuery}
5054
onkeydown={(e) => e.key === "Enter" && controller.handleSearch()}
55+
use:autofocus
5156
/>
5257
{#if controller.isSearching}
5358
<span
@@ -57,20 +62,20 @@
5762
</div>
5863
{/if}
5964
<button
60-
class="btn btn-ghost btn-sm btn-square transition-all duration-150"
61-
title="検索"
65+
class="btn btn-ghost btn-sm btn-square transition-all duration-200"
66+
title="Search"
6267
onclick={() => (controller.showSearch = !controller.showSearch)}
6368
>
6469
<Search
65-
class="size-5 opacity-50 transition-opacity duration-150 hover:opacity-80"
70+
class="size-5 opacity-60 transition-opacity duration-200 hover:opacity-80"
6671
/>
6772
</button>
6873
</div>
6974
</header>
7075

7176
<!-- Search results -->
7277
{#if controller.searchResults.length > 0}
73-
<div class="border-subtle bg-base-200/50 border-b p-2">
78+
<div class="border-subtle bg-base-200/50 border-b p-4">
7479
<SearchResults
7580
results={controller.searchResults}
7681
onResultClick={controller.handleResultClick}

apps/desktop/src/components/channels/ChannelList.svelte

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<div class="flex h-full flex-col">
4343
<!-- Channels section -->
4444
<section class="flex-1 overflow-y-auto">
45-
<header class="flex items-center justify-between px-3 py-2">
45+
<header class="flex items-center justify-between px-4 py-2">
4646
<span class="text-muted text-xs font-medium tracking-wider uppercase">
4747
Channels
4848
</span>
@@ -59,7 +59,7 @@
5959
<a
6060
href={`/orgs/${organizationId}/chat/${channel.id}`}
6161
class={[
62-
"group flex items-center gap-2 rounded px-2 py-1.5 text-sm transition-colors",
62+
"group flex items-center gap-2 rounded px-2 py-2 text-sm transition-colors duration-200",
6363
active
6464
? "bg-primary/15 text-primary"
6565
: "text-base-content/80 hover:bg-base-300 hover:text-base-content",
@@ -84,28 +84,28 @@
8484
</a>
8585
{/each}
8686
{:else}
87-
<div class="text-muted px-2 py-4 text-center text-sm">
88-
読み込み中...
87+
<div class="text-muted px-2 py-4 text-center text-sm opacity-60">
88+
Loading...
8989
</div>
9090
{/if}
9191

9292
{#if channels.data?.length === 0}
93-
<div class="text-muted px-2 py-4 text-center text-sm">
94-
チャンネルがありません
93+
<div class="text-muted px-2 py-4 text-center text-sm opacity-60">
94+
No channels
9595
</div>
9696
{/if}
9797
</nav>
9898
</section>
9999

100100
<!-- DM section -->
101101
<section class="border-subtle border-t">
102-
<header class="flex items-center justify-between px-3 py-2">
102+
<header class="flex items-center justify-between px-4 py-2">
103103
<span class="text-muted text-xs font-medium tracking-wider uppercase">
104104
Direct Messages
105105
</span>
106106
<button
107107
class="btn btn-ghost btn-xs btn-square"
108-
title="新しいDM"
108+
title="New DM"
109109
onclick={() => (showUserSearch = !showUserSearch)}
110110
>
111111
<Plus class="text-muted size-4" />
@@ -132,10 +132,10 @@
132132
<footer class="border-subtle border-t p-2">
133133
<a
134134
href={`/orgs/${organizationId}/personalization`}
135-
class="text-muted hover:bg-base-300 hover:text-base-content flex items-center gap-2 rounded px-2 py-1.5 text-sm transition-colors"
135+
class="text-muted hover:bg-base-300 hover:text-base-content flex items-center gap-2 rounded px-2 py-2 text-sm transition-colors duration-200"
136136
>
137137
<User class="size-4" />
138-
<span>個人設定</span>
138+
<span>Settings</span>
139139
</a>
140140
</footer>
141141
</div>

apps/desktop/src/components/channels/CreateChannelButton.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
<button
4444
class="btn btn-ghost btn-xs btn-square"
45-
title="新しいチャンネル"
45+
title="New channel"
4646
onclick={() => {
4747
modalManager.dispatch(createChannelModalContent);
4848
}}
@@ -58,17 +58,17 @@
5858
>
5959
<input
6060
type="text"
61-
placeholder="チャンネル名"
61+
placeholder="Channel name"
6262
class="input input-bordered"
6363
bind:value={newChannelName}
6464
/>
6565
{#if disabled}
6666
<button type="submit" class="btn btn-primary btn-sm" disabled>
67-
作成中...
67+
Creating...
6868
<span class="loading loading-spinner"></span>
6969
</button>
7070
{:else}
71-
<button type="submit" class="btn btn-primary btn-sm">作成</button>
71+
<button type="submit" class="btn btn-primary btn-sm">Create</button>
7272
{/if}
7373
</form>
7474
{/snippet}

apps/desktop/src/components/chat/EmojiButton.svelte

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@
1010
Button to toggle the emoji palette.
1111
Displays a smiling face emoji icon.
1212
-->
13-
<button class="btn btn-secondary self-end" {onclick}>😀</button>
13+
<button
14+
class="btn btn-ghost btn-sm self-end"
15+
{onclick}
16+
aria-label="Open emoji picker"
17+
>
18+
😀
19+
</button>

apps/desktop/src/components/chat/EmojiPalette.svelte

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script lang="ts">
22
import { Picker } from "emoji-picker-element";
3+
import type { EmojiClickEvent } from "emoji-picker-element/shared";
34
45
interface Props {
56
onClose: () => void;
@@ -49,16 +50,18 @@
4950
5051
const emojiPicker = document.querySelector("emoji-picker");
5152
52-
emojiPicker?.addEventListener("emoji-click", (event) => {
53+
const handleEmojiClick = (event: EmojiClickEvent) => {
5354
const emoji = event.detail.unicode;
5455
if (!emoji) return;
5556
onEmojiSelected(emoji);
56-
});
57+
};
58+
59+
emojiPicker?.addEventListener("emoji-click", handleEmojiClick);
5760
5861
return () => {
5962
document.removeEventListener("click", handleClickOutside);
6063
if (emojiPicker) {
61-
emojiPicker.removeEventListener("emoji-click", () => {});
64+
emojiPicker.removeEventListener("emoji-click", handleEmojiClick);
6265
}
6366
};
6467
});

apps/desktop/src/components/chat/FileAttachmentPreview.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
-->
1616
{#if files.length > 0}
1717
<div class="space-y-2">
18-
<h4 class="text-base-content/70 text-sm font-medium">添付ファイル:</h4>
18+
<h4 class="text-base-content/70 text-sm font-medium">Attached Files:</h4>
1919
<div class="grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-4">
2020
{#each files as file, index (file.name)}
2121
<FilePreview

0 commit comments

Comments
 (0)