Skip to content

feat: add web-based admin interface for resource and room management- #224 - #299

Merged
hamza221 merged 1 commit into
mainfrom
Webinterface
Aug 21, 2026
Merged

feat: add web-based admin interface for resource and room management- #224#299
hamza221 merged 1 commit into
mainfrom
Webinterface

Conversation

@hamza221

@hamza221 hamza221 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Continuing #224
Closes #58.

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

@hamza221 hamza221 added 2. developing Work in progress enhancement New feature or request labels Aug 11, 2026
@hamza221
hamza221 marked this pull request as ready for review August 11, 2026 10:48
@hamza221 hamza221 added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Aug 11, 2026
@hamza221 hamza221 self-assigned this Aug 11, 2026
Comment thread lib/Db/BuildingModel.php
Comment thread LICENSES/Apache-2.0.txt
Comment thread src/components/RoomsSection.vue
Comment thread src/services/adminService.ts Outdated
Comment thread src/CalendarResourceAdmin.vue
Comment thread src/CalendarResourceAdmin.vue
@hamza221 hamza221 added 2. developing Work in progress 3. to review Waiting for reviews and removed 3. to review Waiting for reviews 2. developing Work in progress labels Aug 18, 2026

@GVodyanov GVodyanov left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested and looked thru the frontend code, looks really clean and nice.

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

Add Vue 3 Web Interface for Calendar Resource Management

- Added complete Vue 3 frontend with Vite build system
- Implemented admin UI for Buildings, Stories, Rooms, and Resources
- Fixed Vue reactivity issues with dropdown selections (buildingOptions/storyOptions as data properties)
- Added professional CSS styling with Nextcloud theme integration
- Implemented cache invalidation via IRoomManager/IResourceManager
- Fixed getAllRooms() and getAllResources() to return actual data
- Added AdminController with optional manager dependencies
- Cleaned up excessive debug logging for production
- Added routes for REST API endpoints
- Created AdminSettings integration

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

Add optional room properties: capacity, contact person, room number, and equipment flags (phone, video, TV, projector, whiteboard, wheelchair accessible)

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

Add admin delegation support and fix autoloader issue

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

Fix validation UX - remove required attributes, add programmatic validation

- Removed HTML5 required attributes from all form fields (Gebäude, Stockwerke, Räume, Ressourcen)
- Added placeholder='Pflichtfeld' for visual indication of required fields
- Implemented programmatic validation in addBuilding(), addStory(), addRoom(), addResource()
- Prevents red border issue on input fields after successful form submission
- Provides clear German error messages via alert() dialogs

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

Add multilanguage support (DE/EN) with Nextcloud l10n

- Implemented translation system following Nextcloud standards (like integration_mattermost)
- Created l10n files: de_DE.js, de_DE.json, en.js, en.json
- Wrapped t() and n() functions with auto-injection of app name in adminSettings.js
- All UI strings now translatable (50+ translation keys)
- Removed hardcoded German strings from Vue template
- Fixed UTF-8 encoding issues for German umlauts
- Supports automatic language detection based on Nextcloud user settings
- German translations: Gebäude, Stockwerke, Räume, Ressourcen, etc.
- English translations: Buildings, Stories, Rooms, Resources, etc.

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

chore: add SPDX license headers to frontend files

Add SPDX-FileCopyrightText and SPDX-License-Identifier headers
to all frontend source files according to Nextcloud contribution
guidelines.

Files updated:
- src/CalendarResourceAdmin.vue
- src/adminSettings.js
- l10n/de_DE.js

All files use AGPL-3.0-or-later license to match the project license.

Signed-off-by: Marcel Meyer <meyerm@strato.de>
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix: add missing SPDX headers and strict_types declarations

Addresses code review feedback from @kesselb in #224:

- Add SPDX-FileCopyrightText and SPDX-License-Identifier to:
  * lib/Controller/AdminController.php
  * lib/Settings/AdminSection.php
  * lib/Settings/AdminSettings.php
- Add declare(strict_types=1) to all PHP files
- Rename package.json name to 'calendar-resource-management'

References: #58

Signed-off-by: Marcel Meyer <meyerm@strato.de>
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix: ensure REUSE compliance and fix coding style

This commit addresses all CI failures in #224:

1. REUSE Compliance:
   - Add Apache-2.0 license file to LICENSES/
   - Add SPDX headers to: routes.php, vite.config.mjs, css file
   - Add .license files for JSON and lock files
   - Add license field to package.json

2. XML Schema Compliance:
   - Move <icon> element before <category> in info.xml

3. PHP Coding Style:
   - Run composer cs:fix on all PHP files
   - Apply PSR-12 formatting standards

All files now comply with Nextcloud contribution requirements.

Signed-off-by: Marcel Meyer <meyerm@strato.de>
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix: address all PR #224 review feedback

- Translate all comments to English
- Update SPDX copyright to Nextcloud GmbH and Nextcloud contributors
- Remove CSS file, inject styles via JS bundle (inlineCSS)
- Replace calendar icon with meeting room icon
- Remove l10n files (handled by Transifex)
- Extract API calls into src/services/adminService.js
- Use @nextcloud/axios instead of fetch()
- Use @nextcloud/router instead of OC.generateUrl()
- Replace alert() with showError() from @nextcloud/dialogs
- Replace confirm() with NcDialog component
- Remove console.log statements
- Remove commit_msg.txt and package-lock.json.license
- Remove LICENSES/Apache-2.0.txt (not needed)
- Remove <javascript> tag from info.xml
- Add npm scripts (build, dev, watch, lint, stylelint)
- Use createAppConfig() from @nextcloud/vite-config
- Remove manual registerService() calls (auto DI)
- Hide table headers when no data (v-if)
- Use strict equality (===) for comparisons
- Rename appName to appId to avoid createAppConfig collision

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

build: add eslint and stylelint config and declare frontend dependencies

`npm run lint` could not run: the scripts used the removed `--ext` flag
and the app shipped no eslint or stylelint config, so both linters only
worked by accident when the app was checked out inside a server tree.

- add eslint.config.mjs using @nextcloud/eslint-config v9 flat config
  (recommendedJavascript: Vue 3 with JavaScript script blocks) and
  stylelint.config.js extending @nextcloud/stylelint-config
- declare eslint, stylelint and the stylelint peer configs instead of
  relying on transitive installs
- add the browserslist and engines fields
- annotate package.json and package-lock.json in REUSE.toml, they cannot
  carry a license header themselves

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

refactor(settings): split admin settings into per-entity components

The admin settings were a single 671 line component that violated the
coding style (spaces, semicolons, console logging) and swallowed API
errors.

- split into per-entity section components, each an NcSettingsSection,
  with data loading, error reporting and delete confirmation in the
  parent
- report every failed request via @nextcloud/logger and showError and
  check the `success` flag of create and delete responses
- translate via `translate as t` from @nextcloud/l10n instead of a global
  t/n mixin
- replace the emoji equipment column with a translated list and label the
  delete buttons for screen readers
- replace the hand rolled number input with NcTextField and use design
  system variables, logical properties and scrollable tables

Fixes two defects found on the way:

- NcButton in @nextcloud/vue 9 has no `type` prop, so `type="primary"`
  and `type="error"` rendered unstyled buttons with an invalid HTML type
  attribute; use `variant`
- room creation sent hasVideoConferencing and isWheelchairAccessible,
  but the endpoint reads hasVideo and wheelchairAccessible, so both
  switches were silently discarded

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix: make info.xml schema valid and add the Apache-2.0 license text

The appstore info.xsd has no `icon` element, so `<icon>img/app.svg</icon>`
failed schema validation. The app icon is picked up from img/app.svg by
convention and AdminSection already resolves it, so the element is not
needed.

img/app.svg is annotated as Apache-2.0 in REUSE.toml but the matching
license text was missing from LICENSES, which made the reuse lint fail
once the file was added.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix: drop the out-of-scope calendar backend changes

getAllRooms() and getAllResources() have returned an empty array since the
initial commit and nothing calls them: the sync job in
OC\Calendar\ResourcesRoomsUpdater reads through listAllRooms()/getRoom()
and listAllResources()/getResource(). Implementing them with a plain
findAll() would also have bypassed the visibility filtering that
listAllRooms() gained with findAllVisibleUIDs(), handing out restricted
rooms and resources.

Unrelated to the admin settings anyway, so leave them as they are.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix(settings): authorize delegated admins and harden the admin API

The endpoints were reachable by admins only despite AdminSettings
implementing IDelegatedSettings, accepted any parent ID, and returned raw
exception messages to the client.

- add #[AuthorizedAdminSetting] to every endpoint. It has to be per method
  because MiddlewareUtils::getAuthorizedAdminSettingClasses() only reads
  method attributes
- validate that the story or building exists before inserting, like the
  create commands do, and drop the storyId/buildingId fallback of 1
- log unexpected failures with the exception and answer with a fixed
  message and Http::STATUS_* instead of $e->getMessage(); missing input is
  a 400, an unknown entity a 404
- move building and story persistence into BuildingService and a new
  StoryService instead of using the mappers from the controller
- replace appinfo/routes.php with #[FrontpageRoute]; the generated URLs are
  unchanged, so the frontend keeps working
- use constructor promotion, return types and camelCase method names,
  inject the room and resource managers non-nullable (IManager::update()
  exists since 30.0.0 and the app requires 31) and generate UIDs with
  ISecureRandom
- drop the deprecated IInitialStateService and the initial state that no
  code read

The error messages are deliberately untranslated, the frontend shows its
own translated message and only logs the response.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

test: cover the admin API and the resource services

Adds unit tests for the input validation, the parent ID checks, the error
mapping and the calendar backend updates of AdminController, and for
BuildingService, StoryService, RoomService and ResourceService.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix(design): design review

- one shared max width for all form fields, selects and submit buttons, only
  the room table is allowed to be wider because of its column count
- tables lead each section, get rounded corners and a --color-border-dark
  border, and their cells leave 4px around the row actions
- delete buttons are tertiary icon buttons, labelled for screen readers
- add buttons are wide, carry a plus icon and name what they add
- the add buttons show a spinner and refuse further clicks while the create
  request runs, which made it possible to add an entry twice
- the contact person is picked from an account dropdown instead of typing a
  user id, backed by a new endpoint that searches accounts server side
- capacity drops the "(persons)" hint
- the interface calls stories floors, which is the more common wording. The
  entity keeps its name because the database, the commands and the public
  IRoomMetadata::BUILDING_STORY key cannot be renamed

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

refactor: use typescript

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

fix: use json serialize

Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
@hamza221
hamza221 enabled auto-merge August 21, 2026 14:39
@hamza221
hamza221 merged commit c146f8c into main Aug 21, 2026
35 checks passed
@hamza221
hamza221 deleted the Webinterface branch August 21, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide Admin UI for Creating and Editing Resources

4 participants