- Move loadProjects() call from created() to handleDialogOpen()
- Remove allProjects check from ensureSelectedProjectLoaded()
- Projects now load only when dialog is opened, improving initial page load performance
- ensureSelectedProjectLoaded() now directly fetches project by handleId when needed
Refactor selectedProject computation to use separate storage instead of
relying on allProjects array. This fixes a bug where the selected project
wouldn't display after page refresh if it wasn't in the initial allProjects
batch.
Changes:
- Add selectedProjectData property to store selected project independently
- Simplify selectedProject computed to return selectedProjectData directly
- Add fetchProjectByHandleId() to fetch single project by handleId
- Add ensureSelectedProjectLoaded() to check allProjects first, then fetch
- Update handleProjectLinkAssigned() to store directly in selectedProjectData
- Remove band-aid solution of adding selected projects to allProjects array
- Update startEditing() and cancelEditing() to ensure selected project loads
- Call ensureSelectedProjectLoaded() in created() lifecycle hook
This ensures the selected project always displays correctly, even when:
- Selected from search results (not in allProjects)
- Page is refreshed (allProjects reloads without selected project)
- Project is in a later pagination batch
Implement server-side search for projects using API endpoint with
pagination support via beforeId parameter. Contacts continue using
client-side filtering from complete local database.
- Add PlatformServiceMixin for internal apiServer access
- Implement performProjectSearch() with pagination
- Update infinite scroll to handle search pagination
- Add search lifecycle management and error handling
No breaking changes to parent components.
Add server-side pagination to EntityGrid component for projects, enabling
infinite scrolling to load all available projects instead of stopping after
the initial batch.
Changes:
- EntityGrid: Add loadMoreCallback prop to trigger server-side loading when
scroll reaches end of loaded projects
- OnboardMeetingSetupView: Update loadProjects() to support pagination with
beforeId parameter and add handleLoadMoreProjects() callback
- MeetingProjectDialog: Accept and pass through loadMoreCallback to EntityGrid
- GiftedDialog: Add pagination support to loadProjects() and
handleLoadMoreProjects() callback
- EntitySelectionStep: Accept and pass through loadMoreCallback prop to
EntityGrid when showing projects
This ensures users can access all projects in MeetingProjectDialog and
GiftedDialog by automatically loading more as they scroll, matching the
behavior already present in DiscoverView.
All project uses of EntityGrid now use pagination by default.
Replace Project Link text input with interactive selection dialog
using new MeetingProjectDialog component. Dialog displays user's
projects with icons and issuer information, following the same
pattern as ProjectRepresentativeDialog.
- Create MeetingProjectDialog with EntityGrid integration
- Add clickable project field with icon, name, and issuer display
- Load projects from /api/v2/report/plansByIssuer endpoint
- Show issuer name instead of handleId for better UX
- Refactor loadProjects to remove unused rowId field
EntityGrid's recentContacts assumes contacts are sorted by date added
(newest first), but ProjectRepresentativeDialog was receiving contacts
sorted alphabetically from NewEditProjectView, causing it to show
different "Recently Added" contacts than GiftedDialog.
- Changed NewEditProjectView to use $contactsByDateAdded() instead of
$getAllContacts()
- Added documentation comments to EntityGrid.vue to prevent this issue
in future reuses
- Remove conflictChecker prop (always passed as no-op function)
- Remove unused emitCancel method and cancel event handling
- Simplify handleEntitySelected by removing unnecessary type check
- Update NewEditProjectView to remove conflict-checker binding and empty cancel handler
The conflictChecker prop was not needed since representative selection
doesn't require conflict detection. The cancel event was never emitted
and the parent handler was empty, so both were removed.
Replace the plain text input for authorized representative with an
interactive contact selection interface that provides better UX and
maintains data consistency.
Changes:
- Add ProjectRepresentativeDialog component using EntityGrid for contact selection (excludes "You" and "Unnamed" special entities)
- Replace text input with clickable field showing contact icon, name, and DID
- Implement conditional UI states: initial "Assign..." placeholder vs assigned representative display with unset button
- Refactor selectedRepresentative to computed property derived from agentDid (single source of truth, prevents sync issues)
- Inline representativeDisplayName for simplicity
- Support changing representative by clicking on assigned field
- Support unsetting representative via trash button
The new implementation ensures agentDid remains the authoritative state while selectedRepresentative is automatically computed, preventing the previously possible desync when agentDid was set directly (e.g., via the
"make original owner an authorized representative" button).
Consolidate organizerAdmitAndAddWithVisibility() and
memberAddContactWithVisibility() into a single unified method
processSelectedMembers() that handles both organizer and member
modes based on the isOrganizer prop.
- Remove redundant handleMainAction() wrapper method
- Update template to call processSelectedMembers directly
- Reduce code duplication by ~30% (140 lines → 98 lines)
- Maintain identical functionality for both modes
This simplifies the component structure and makes the processing
logic easier to maintain.
Remove dialogType prop and consolidate to use only isOrganizer prop.
- Remove dialogType prop from BulkMembersDialog component
- Replace all dialogType checks with isOrganizer boolean checks
- Add comments clarifying isOrganizer true/false meanings
- Remove dialog-type prop binding from MembersList component
This simplifies the component API while maintaining the same functionality.
Add infinite scroll functionality to EntityGrid component using VueUse's
useInfiniteScroll composable to handle large volumes of entities efficiently.
Changes:
- Integrate @vueuse/core useInfiniteScroll composable
- Add infinite scroll state management (displayedCount, reset function)
- Configure initial batch size (20 items) and increment size (20 items)
- Update displayedEntities, alphabeticalContacts to support progressive loading
- Add canLoadMore() logic for people, projects, and search modes
- Reset scroll state when search term or entities prop changes
- Remove maxItems prop (replaced by infinite scroll)
- Simplify displayEntitiesFunction signature (removed maxItems parameter)
- Update EntitySelectionStep and test files to remove max-items prop
Technical details:
- Uses template ref (scrollContainer) to access scrollable container
- Recent contacts (3) count toward initial batch for people grid
- Special entities (You, Unnamed) always displayed, don't count toward limits
- Infinite scroll works for both entity types and search results
- Constants are configurable at top of component (INITIAL_BATCH_SIZE, INCREMENT_SIZE)
This improves performance and UX when displaying large lists of contacts or
projects by loading content progressively as users scroll.
When displaying contacts (not search results), show the 3 most recently
added contacts at the top with a "Recently Added" heading, followed by
the rest sorted alphabetically with an "Everyone Else" heading.
- Add recentContacts and alphabeticalContacts computed properties
- Hide "You" and "Unnamed" special entities during search
- Only show search spinner when actively searching with a term
- Style section headings with uppercase, improved spacing, and borders
Add contextual feedback message when a search term is entered but no matching entities are found. The message dynamically adjusts its wording based on whether searching for people or projects.
- Add search-as-you-type functionality with 500ms debounce
- Implement search across contact names and DIDs, project names and handleIds
- Add loading spinner and dynamic clear button
- Add $contactsByDateAdded() method to PlatformServiceMixin for newest-first sorting
- Update GiftedDialog to use date-based contact ordering
- Maintain backward compatibility with existing $contacts() alphabetical sorting
- Add proper cleanup for search timeouts on component unmount
The search feature provides real-time filtering with visual feedback,
while the new sorting ensures recently added contacts appear first.
- Remove ShowAllCard component and all related functionality
- Remove showAllRoute, showAllQueryParams, and hideShowAll props
- Remove shouldShowAll computed property from EntityGrid
- Clean up ShowAll-related code from EntitySelectionStep and GiftedDialog
- Delete ShowAllCard.vue component file
- Update component documentation to reflect removal
This simplifies the entity selection interface by removing the navigation
card that allowed users to view all entities in a separate view.
- Replace individual text props with single isOrganizer boolean prop
- Add computed properties for title, description, buttonText, and emptyStateText
- Simplify parent component interface by removing text prop passing
- Update quote style from single to double quotes for consistency
- Improve component encapsulation and maintainability
- Merge AdmitPendingMembersDialog and SetBulkVisibilityDialog into single BulkMembersDialog
- Add dynamic props for dialog type, title, description, button text, and empty state
- Support both 'admit' and 'visibility' modes with conditional behavior
- Rename setVisibilityForSelectedMembers to addContactWithVisibility for clarity
- Update success counting to track contacts added vs visibility set
- Improve error messages to reflect primary action of adding contacts
- Update MembersList to use unified dialog with role-based configuration
- Remove unused libsUtil import from MembersList
- Update comments and method names to reflect unified functionality
- Rename closeMemberSelectionDialogCallback to closeBulkMembersDialogCallback
This consolidation eliminates ~200 lines of duplicate code while maintaining
all existing functionality and improving maintainability through a single
source of truth for bulk member operations.
- Add tfoot with "Select All" checkbox to AdmitPendingMembersDialog
- Add tfoot with "Select All" checkbox to SetBulkVisibilityDialog
- Both footer checkboxes sync with header checkboxes for consistent UX
- Users can now select/deselect all members from top or bottom of table
- Add missing <style scoped> section to FeedFilters.vue to fix PostCSS error
The PostCSS error was occurring because Vue single-file components require
a <style> section, even if empty, for proper CSS processing.
- Fix undefined admitted property for non-organizers by defaulting to true
- Update conditional styling logic to show blue background for non-admitted current user
- Add hand icon indicator for current user in members list
- Improve sorting to prioritize current user after organizer
- Refactor currentUserInList variable inline for cleaner code
- Update text color and hourglass icon conditions to include current user
The server was returning undefined for the admitted property when non-organizers
viewed the members list, causing incorrect styling. Non-organizers now properly
see their admission status and get appropriate visual indicators.
- Add condition to only show "add to contacts" instruction when there are members who are not already contacts
- Use existing getNonContactMembers() method to check for non-contact members
- Fix line length warning by breaking long comment into multiple lines
- Simplify success message generation using ternary operators
- Remove visibilitySetCount due to its implied nature
- Handle case when contactAddedCount is 0 by omitting contact-related text
- Use more compact logic that only applies ternaries to variable parts
- Maintain proper pluralization for both admitted members and contacts
The message now shows:
- "n member/s admitted." when no contacts added
- "n member/s admitted and added as contact/s." when counts equal
- "n member/s admitted, n added as contact/s." when counts differ
- Add stopAutoRefresh() calls before showing confirmation dialogs
- Add startAutoRefresh() calls after dialog interactions complete
- Ensure auto-refresh resumes properly in all dialog callback paths
- Fix missing onCancel handler for contact confirmation dialog
This prevents auto-refresh from interfering with user interactions
during member admission workflows while ensuring it resumes afterward.
- Remove scoped CSS styles for .dialog-overlay and .dialog from AdmitPendingMembersDialog.vue
- Remove scoped CSS overflow style from FeedFilters.vue dialog
- Update Tailwind .dialog utility class to include max-height and overflow-y-auto
- Consolidate dialog styling into reusable Tailwind components for consistency