feat(resources): Visual room browser with building grouping and filters#7996
feat(resources): Visual room browser with building grouping and filters#7996Rikdekker wants to merge 12 commits intonextcloud:mainfrom
Conversation
…ilters Replace the minimal resource picker with a comprehensive room browser that loads all room principals upfront and provides real-time availability checking, client-side filtering, and building-based grouping. Changes: - ResourceList.vue: full rewrite with search, available-only toggle, min capacity filter, dynamic building and facility chips, collapsible building groups, and room cards with availability status - ResourceRoomCard.vue: new component showing room name, availability badge, capacity, floor, room type, and add/remove action - principal.js: extract room-specific DAV properties (seating capacity, room type, features, building address, room number) and derive a structured location string for the LOCATION field - resourceProps.js: add formatFacility() helper and extend getAllRoomTypes() with additional room types Signed-off-by: Rik Dekker <rik@shalution.nl>
Replace directional CSS properties with logical equivalents: - margin-right → margin-inline-end - text-align: left → text-align: start - padding-left → padding-inline-start - border-left → border-inline-start Signed-off-by: Rik Dekker <rik@shalution.nl>
Add room property fields (roomSeatingCapacity, roomType, roomAddress, roomFeatures, roomBuildingName, roomBuildingAddress, roomNumber) to all existing principal test expectations. Add a new test case for a room principal with actual room DAV properties to verify the building name derivation and address formatting logic. Signed-off-by: Rik Dekker <rik@shalution.nl>
…mCard ResourceList.vue: - Replace deprecated :value with v-model on NcTextField - Use camelCase for component attributes and event names - Fix import ordering (perfectionist/sort-imports) - Add curly braces to all if/else blocks - Replace deprecated Vue.set with direct property assignment - Split multi-statement forEach bodies to separate lines - Remove self-closing slash from void <input> element - Fix function-paren-newline style ResourceRoomCard.vue: - Replace deprecated :type with :variant on NcButton - Add emits option declaring removeRoom and addRoom - Use camelCase for emitted event names - Add required newlines between multi-line props Signed-off-by: Rik Dekker <rik@shalution.nl>
4aa6f97 to
f92802f
Compare
Move debounce and pinia (external group) before @nextcloud/vue/components and vue-material-design-icons (vue group). Remove blank lines between import groups as required by newlinesBetween: 0. Signed-off-by: Rik Dekker <rik@shalution.nl>
e13919c to
5f1ab97
Compare
…st mocks Move FACILITY_LABELS from a module-level constant to a lazily-evaluated function. The module-level t() calls were executed at import time, before Vitest test mocks were active, which polluted the @nextcloud/l10n mock state and caused 54 unrelated tests to fail. This follows the same pattern as getAllRoomTypes() which also evaluates t() inside a function body rather than at module scope. Signed-off-by: Rik Dekker <rik@shalution.nl>
| @@ -0,0 +1,204 @@ | |||
| <!-- | |||
| - SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors | |||
…bility The vmForks pool has a known issue with Vitest v4 where vi.mock() hoisting breaks when V8 coverage instrumentation is active (vitest-dev/vitest#8861). This causes 54 tests to fail under `vitest --run --coverage` while passing under `vitest --run`. Switch to vmThreads which provides the same VM isolation and CSS transformation support without the coverage mock hoisting bug. Signed-off-by: Rik Dekker <rik@shalution.nl>
|
Hi @Rikdekker I had a quick look at the changes you are suggesting. I am not sure if packing all that information in to that corner of the editor is a good idea, I think maybe adding a room selection modal might be a better approache Lets see what design thinks? @nextcloud/designers @nimishavijay |
Agreed! We can also give some ideas about reorganizing the page |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Address PR review feedback: - Convert ResourceRoomCard.vue and ResourceList.vue to TypeScript with Composition API and <script setup> syntax - Delete unused ResourceListItem.vue and ResourceListSearch.vue - Fix SPDX copyright year to 2026 - Fix ESLint issues in vitest.config.js (import order, trailing comma, semicolon) Signed-off-by: Rik Dekker <rik@shalution.nl> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The vmThreads/vmForks pools have a non-deterministic issue with vi.mock() hoisting when V8 coverage is active (vitest-dev/vitest#8861). Switch to the standard forks pool which uses real Node.js child processes and handles mock hoisting reliably. Signed-off-by: Rik Dekker <rik@shalution.nl> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The forks pool cannot transform CSS files from @nextcloud/vue, causing "Unknown file extension .css" errors. Switch back to vmThreads (which handles CSS via the Vite pipeline) but disable fileParallelism to prevent the non-deterministic vi.mock() hoisting failures when V8 coverage is active (vitest-dev/vitest#8861). Signed-off-by: Rik Dekker <rik@shalution.nl> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use vmForks pool (required for CSS transformation) with singleFork option to serialize test execution in a single VM fork, preventing the non-deterministic vi.mock() hoisting failures when V8 coverage is active (vitest-dev/vitest#8861). Signed-off-by: Rik Dekker <rik@shalution.nl> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent loading room data for non-organizers by checking isViewedByOrganizer before calling loadAllRooms(). Addresses review feedback from SebastianKrupinski on PR nextcloud#7996. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent loading room data for non-organizers by checking isViewedByOrganizer before calling loadAllRooms(). Addresses review feedback from SebastianKrupinski on PR nextcloud#7996. Signed-off-by: Rikdekker <Rikdekker@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6fdc817 to
27c347b
Compare
|
Friendly ping @nextcloud/designers @nimishavijay — would love your input on the modal vs inline approach so we can move forward. Happy to prepare mockups for either direction. In the meantime I've addressed the code review feedback from @SebastianKrupinski:
|
|
@jancborchardt thanks for the feedback. What do you think of this design proposal? |
jancborchardt
left a comment
There was a problem hiding this comment.
The interaction is good, but the layout was nice as before with attendees 2/3 (left column) and the room selector 1/3 (right column). That will also help people switching over from MS to adjust quicker.
|
@jancborchardt What do you think about this? We think it is quite busy to have all the information at the same time on one screen. |
jancborchardt
left a comment
There was a problem hiding this comment.
@Rikdekker right, that's a valid concern. The approach with a (nonstandard) sidebar on top of a modal is a bit strange though.
Instead what do you think about having a button "Room finder" (note we use sentence case) in the right column, same level as the sharing input, which then expands that info.
Interaction-wise it works similar to your proposal, but is a bit more integrated.
|
@jancborchardt Here's a demo of a new proposal for the calendar event modal including room finder interaction (filtering, availability, selecting a room): DocumentationI've written up detailed documentation for this feature:
Looking forward to you feedback! |
|
Hello there, We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 Thank you for contributing to Nextcloud and we hope to hear from you soon! (If you believe you should not receive this message, you can add yourself to the blocklist.) |
|
@jancborchardt can you give an update of the status of this PR? |
|
@jancborchardt Friendly reminder — this has been waiting on design feedback for about 7 weeks now. I'd love to move this forward. I've iterated on the design based on your earlier input and posted a working demo with documentation on March 2nd. I'm happy with the current approach — it balances usability and information density well without overloading the modal. Could you take another look and share any remaining concerns? If there are specific things you'd like adjusted I'm happy to discuss, but I'd like to avoid the PR going stale. Thanks! |
|
Hello! Thank you for taking the time to contribute :) From your latest screencast I see that there are many different updates that go beyond the scope of just room management, and the result of the room management UI is quite different from what @jancborchardt had suggested as well. Please update the UI with the feedback in mind (we do want to be rather similar to Outlook, but with Nextcloud's design language, and good alignment of text and icons), and let's keep the scope of this to just room management so it is easier for the developers to review :) |







Summary
Replace the minimal resource picker (search-only, max 3 suggestions) with a comprehensive visual room browser that shows all available rooms at once, grouped by building.
Screenshots
Context
This room browser was developed as part of RoomVox, a CalDAV-based room booking backend for Nextcloud. Full documentation of the patch and its data flow is available at calendar-patch.md.
Changes
ResourceList.vue— full rewrite: loads all room principals, checks availability via free/busy, groups by building, client-side filtering with text/capacity/building/facility filtersResourceRoomCard.vue— new component: compact card with availability badge, capacity, floor, room type, add/remove buttonprincipal.js— extract room-specific DAV properties (seating capacity, room type, features, building address, room number) and derive a structured LOCATION stringresourceProps.js— addformatFacility()helper and extendgetAllRoomTypes()with additional room types (board room, conference room, rehearsal room, studio, outdoor area)Test plan
🤖 Generated with Claude Code