Repository navigation
Feature/contacts pane redesign - #301
Conversation
|
So far so good. |
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
…right place Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
timea-solid
left a comment
There was a problem hiding this comment.
While any is a good start, we should improve it to be more specific at some point.
Good work!
| type Visibility = 'public' | 'private' | null | ||
|
|
||
| /** Globe and lock marks for the visibility badge, sized to its text. */ | ||
| const globeIcon = html` |
There was a problem hiding this comment.
don't we have this icons on lucide?
|
|
||
| /** The empty state's circled address-book icon; the wording next to it is | ||
| * plain HTML in renderEmpty. */ | ||
| const emptyIllustration = html` |
There was a problem hiding this comment.
Pls try and use lucide icons directly as we have in solid-ui or profile-pnae
Take staging's dependency versions, drop the legacy contactsPane.js the redesign already replaced, and carry its add-contact dialog test over to the Lit components. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017U9rvGpQqMM76GgeRkgjUJ
- Import lucide icons via ~icons/lucide/* in each component instead of the removed solid-ui/components/icons barrel, and replace the hand-drawn SVGs (visibility badge globe/lock, empty-state address book, fallback avatar) with lucide equivalents. - Bundle ~icons imports in the build rather than leaving them external. - Replace loose any types in the presenter, logic modules and components. - Give the groups section its own accessible name (the heading it referred to lives inside the header's shadow root). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017U9rvGpQqMM76GgeRkgjUJ
|
it looks really nice! Great work! just a couple suggestions. I realized recently you can use the solid-ui-combobox for the select and it will give the same selection style as we are using in profile-pane. also, it would be good if the count on the groups updated when you add a contact. Amazing! |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Maintenance actions can mutate or report success incorrectly, and search advertises unsupported fields.
Review effort: Balanced
Findings: 1
Open (6)
What changed in this PR
Redesigns the contacts pane for issue #295 using Lit components and Solid UI controls while migrating legacy JavaScript to TypeScript.
Changes:
- Introduces componentized address-book, group, people, search, details, tools, and dialog interfaces.
- Extracts maintenance logic and modernizes contact/group operations.
- Updates styling, icons, TypeScript strictness, build configuration, and tests.
| File | Description |
|---|---|
vite.config.mts |
Bundles generated icon modules. |
tsconfig.test.json |
Includes ambient test declarations. |
tsconfig.json |
Enables implicit-any checking. |
test/unit/setup.ts |
Tightens mock types. |
test/unit/pane.accessibility.test.ts |
Adapts pane accessibility tests. |
test/unit/modals.accessibility.test.ts |
Tests new dialogs with axe. |
test/unit/localUtils-modal.test.ts |
Tests dialogs and deletion controls. |
test/unit/data-reformat-test.test.ts |
Adapts search interaction tests. |
test/helpers/setup.ts |
Polyfills form-associated internals. |
src/webidControl.ts |
Adds TypeScript annotations. |
src/toolsLogic.ts |
Adds maintenance-tool logic. |
src/styles/toolsPane.css |
Removes legacy tool styles. |
src/styles/localUtils.css |
Removes legacy modal styles. |
src/styles/individual.css |
Updates contact-card presentation. |
src/styles/contactsPane.css |
Implements redesigned responsive layout. |
src/rdfFormsHelper.ts |
Types RDF form helpers. |
src/mugshotGallery.ts |
Types gallery and upload behavior. |
src/mintNewAddressBook.ts |
Refactors typed minting flow. |
src/localUtils.ts |
Migrates utilities and dialog integration. |
src/localUtils.js |
Removes legacy utility implementation. |
src/individual.ts |
Types individual rendering. |
src/groupMembershipControl.ts |
Integrates the new delete control. |
src/debug.ts |
Adds typed logging utilities. |
src/debug.js |
Removes JavaScript logging utilities. |
src/contactsPane.ts |
Introduces the component-based pane entry. |
src/contactLogic.ts |
Types contact and group operations. |
src/components/tools/Tools.ts |
Adds the maintenance-tools component. |
src/components/tools/Tools.styles.css |
Styles the tools component. |
src/components/tools/index.ts |
Exports the tools component. |
src/components/sharing-modal/SharingModal.ts |
Adds the sharing dialog. |
src/components/sharing-modal/SharingModal.styles.css |
Styles sharing content. |
src/components/sharing-modal/index.ts |
Exports the sharing dialog. |
src/components/search/Search.ts |
Adds the contact-search component. |
src/components/search/Search.styles.css |
Styles contact search. |
src/components/search/index.ts |
Exports contact search. |
src/components/people-list/PeopleList.ts |
Adds the interactive people list. |
src/components/people-list/PeopleList.styles.css |
Styles people rows and menus. |
src/components/people-list/index.ts |
Exports the people list. |
src/components/new-group-modal/NewGroupModal.ts |
Adds group-creation dialog. |
src/components/new-group-modal/NewGroupModal.styles.css |
Styles group creation. |
src/components/new-group-modal/index.ts |
Exports group creation. |
src/components/group-bar/index.ts |
Exports the group bar. |
src/components/group-bar/GroupBar.ts |
Adds group filtering and selection. |
src/components/group-bar/GroupBar.styles.css |
Styles the group column. |
src/components/details-section/index.ts |
Exports contact details. |
src/components/details-section/DetailsSection.ts |
Manages details-pane states. |
src/components/delete-button/index.ts |
Exports deletion controls. |
src/components/delete-button/DeleteButton.ts |
Adds reusable confirmed deletion. |
src/components/delete-button/DeleteButton.styles.css |
Styles the delete control. |
src/components/confirm-modal/index.ts |
Exports confirmation dialogs. |
src/components/confirm-modal/ConfirmModal.ts |
Adds the confirmation dialog. |
src/components/confirm-modal/ConfirmModal.styles.css |
Styles confirmation dialogs. |
src/components/alert-modal/index.ts |
Exports alert dialogs. |
src/components/alert-modal/AlertModal.ts |
Adds the alert dialog. |
src/components/alert-modal/AlertModal.styles.css |
Styles alert dialogs. |
src/components/address-book/index.ts |
Exports the address-book component. |
src/components/address-book/AddressBook.ts |
Coordinates the redesigned view. |
src/components/address-book-header/index.ts |
Exports the address-book header. |
src/components/address-book-header/AddressBookHeader.ts |
Adds header actions and visibility. |
src/components/address-book-header/AddressBookHeader.styles.css |
Styles the redesigned header. |
src/components/add-contact-modal/AddContactModal.ts |
Types and renames contact creation. |
src/addressBookPresenter.ts |
Migrates presenter behavior to TypeScript. |
src/addressBookPresenter.js |
Removes the JavaScript presenter. |
package.json |
Adds icon tooling dependencies. |
package-lock.json |
Locks icon tooling dependencies. |
eslint.config.mjs |
Enforces modern TypeScript syntax. |
declarations.d.ts |
Declares generated icon modules. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| } catch (e) { | ||
| debug.error('Error loading groups. Stack: ' + e) | ||
| log('Error loading groups or name index. If it persists, contact your admin.') | ||
| } |
| <h2 id="addressBook-heading" tabindex="-1">${this.selectedGroupName ?? 'All Contacts'}</h2> | ||
| ${this.renderVisibilityBadge()} | ||
| </div> | ||
| <p>Search contacts by name, email, WebID, or profile URL</p> |
| log('' + totalContacts + ' contacts loaded. ') | ||
| const groups = dedupedGroups(book) | ||
| log('' + groups.length + ' total groups. ') | ||
| log('' + Object.keys(selectedGroups).length + ' selected groups. ') |
| export function checkAccess (selectedGroups: Record<string, boolean>, log: Log) { | ||
| function doCard (card: NamedNode) { | ||
| UI.acl.fixIndividualCardACL(card, (message: string) => log(message), (ok: boolean, message: any) => { |
| let groupOfUngrouped: any = null | ||
| try { | ||
| groupOfUngrouped = await saveNewGroup(book, 'No group') | ||
| } catch (_e) { | ||
| // The group may exist already; adding below still works then. | ||
| } | ||
|
|
||
| if (!(await confirm(`Add the ${groupless.length} contacts without groups to a 'No group' group?`))) { | ||
| return false | ||
| } |
| } catch (e) { | ||
| log('Error saving uniques: ' + e) | ||
| } |
|
@m5x5 do you have time to address the copilot findings? |
kb.any/kb.each return Node | null, but fetcher.load only takes named nodes, so the "as NamedNode" casts hid a missing or literal index. - Add an isNamedNode guard that wraps rdflib's and narrows to rdflib's NamedNode class, so it can be swapped for rdflib's once that narrows to the class itself. - Add bookIndex(), which takes the first named node for the name or group index and throws when there is none, instead of loading null. - Filter group and card lists with isNamedNode instead of casting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Addresses the Copilot review on toolsLogic.ts. - findGroupless: rethrow when the index or a group fails to load. A partial store reported grouped contacts as groupless, and "Put all individuals with no group..." then moved them. - checkAccess: return a promise that settles once every card's ACL repair has finished, and fail when any of them failed, so the Tools button stops loading only at the end. solid-ui's fixIndividualACL never calls back when the ACL is already right, so its "Nice - same ACL" log line also counts as done. - fixGroupless: ask before creating the "No group" group, so Cancel leaves the book untouched, and let creation errors propagate. - saveCleanPeople / saveCleanGroup: rethrow after logging, so a failed PUT is no longer reported as "Done!". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GroupBar keeps a deselected group as a false entry in selectedGroups, so Statistics over-reported the selection and "Check individual contact access" also walked deselected groups. Addresses the Copilot review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The header promised these fields, but the filter only matched names (Copilot review). - Match every word of the query against the name, all email addresses, every vcard:url and any owl:sameAs of the contact. - Update the search placeholder to say the same as the header. Emails and URLs come from each card, which loads in the background, so right after opening a book a contact may only be found by name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new member changes the counts in the group bar, which other handlers already refresh. Suggested in review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Matches the type pickers in profile-pane's edit dialogs, as suggested in review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Show the tools in a contacts-pane-tools-modal dialog instead of the details section, with the log below the buttons. The dialog's width is fixed and its content scrolls, so a growing log does not resize it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…5/contacts-pane into feature/contactsPaneRedesign


#295