Skip to content

Feat/add calendar delegation features#8085

Merged
GVodyanov merged 2 commits into
mainfrom
feat/add-calendar-delegation-features
Jun 4, 2026
Merged

Feat/add calendar delegation features#8085
GVodyanov merged 2 commits into
mainfrom
feat/add-calendar-delegation-features

Conversation

@GVodyanov

@GVodyanov GVodyanov commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

For #2706
Make sure you're on an updated server master the cherry-pick nextcloud/server#60648 to test

@GVodyanov GVodyanov self-assigned this Mar 22, 2026
@GVodyanov GVodyanov added the 2. developing Work in progress label Mar 22, 2026
@codecov

codecov Bot commented Mar 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/store/principals.js 0.00% 6 Missing and 1 partial ⚠️
src/services/caldavService.js 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@GVodyanov GVodyanov force-pushed the feat/add-calendar-delegation-features branch from da7ae86 to 654e770 Compare March 22, 2026 22:22
Comment thread src/services/delegationService.js Outdated
@GVodyanov GVodyanov marked this pull request as ready for review May 4, 2026 08:17
@ChristophWurst ChristophWurst mentioned this pull request May 4, 2026
10 tasks
@GVodyanov

Copy link
Copy Markdown
Contributor Author

Here's what everything looks like

2026-05-04-121811_2560x1440_scrot 2026-05-04-121834_2560x1440_scrot 2026-05-04-121650_2560x1440_scrot

@kra-mo kra-mo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From the design side:

"Select a user" and "Search for a user…" are redundant, it's fine to just have the second if it's baked into the component anyway, so without the title. The input field should also be full-width, and Add should be a primary button.

I wonder why delegation should be its own item in the sidebar instead of just a section in Settings? I'd rather have it just there. And at that point, have + Add delegate be full-width as well.

@hamza221

hamza221 commented May 5, 2026

Copy link
Copy Markdown
Contributor

The pre-existing sharing logic doesn't work for delegation

image

A clear indication of Calendar "owner" should be visible
image

@GVodyanov

Copy link
Copy Markdown
Contributor Author

From the design side:

"Select a user" and "Search for a user…" are redundant, it's fine to just have the second if it's baked into the component anyway, so without the title. The input field should also be full-width, and Add should be a primary button.

I wonder why delegation should be its own item in the sidebar instead of just a section in Settings? I'd rather have it just there. And at that point, have + Add delegate be full-width as well.

Thanks for the review! How does this look?

image image (I know that having delegates under delegation looks a little weird as title organization but that's the setting section with the form group component, and u can't not have titles for both)

@GVodyanov GVodyanov requested a review from kra-mo May 5, 2026 17:20
@GVodyanov

Copy link
Copy Markdown
Contributor Author

It took me a while to figure out but here is everything working

image

@GVodyanov

Copy link
Copy Markdown
Contributor Author

You get the icon here to show its delegated

image

@GVodyanov GVodyanov force-pushed the feat/add-calendar-delegation-features branch 2 times, most recently from 0dd4839 to f50f37d Compare May 6, 2026 15:04
@hamza221 hamza221 added 3. to review Waiting for reviews and removed 2. developing Work in progress labels May 6, 2026

@kra-mo kra-mo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good from the design side :)

@SebastianKrupinski

SebastianKrupinski commented May 7, 2026

Copy link
Copy Markdown
Contributor

Tested.

Found error when delegator has a shared calendar

{
  "reqId": "axdoc6W1q46YCrgBbdrq",
  "level": 0,
  "time": "2026-05-07T13:00:21+00:00",
  "remoteAddr": "127.0.0.1",
  "user": "user2",
  "app": "webdav",
  "method": "PROPFIND",
  "url": "/remote.php/dav/calendars/user1/",
  "scriptName": "/remote.php",
  "message": "Calendar with name 'company_shared_by_admin' could not be found",
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0",
  "version": "34.0.0.3",
  "exception": {
    "Exception": "Sabre\\DAV\\Exception\\NotFound",
    "Message": "Calendar with name 'company_shared_by_admin' could not be found",
    "Code": 0,
    "Trace": [
      {
        "file": "/var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/DavAclPlugin.php",
        "line": 86,
        "function": "checkPrivileges",
        "class": "OCA\\DAV\\Connector\\Sabre\\DavAclPlugin",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/Server.php",
        "line": 163,
        "function": "propFind",
        "class": "OCA\\DAV\\Connector\\Sabre\\DavAclPlugin",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/event/lib/WildcardEmitterTrait.php",
        "line": 89,
        "function": "OCA\\DAV\\Connector\\Sabre\\{closure}",
        "class": "OCA\\DAV\\Connector\\Sabre\\Server",
        "type": "->",
        "args": [
          "*** sensitive parameters replaced ***"
        ]
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php",
        "line": 1052,
        "function": "emit",
        "class": "Sabre\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php",
        "line": 984,
        "function": "getPropertiesByNode",
        "class": "Sabre\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php",
        "line": 1664,
        "function": "getPropertiesIteratorForPath",
        "class": "Sabre\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php",
        "line": 1649,
        "function": "writeMultiStatus",
        "class": "Sabre\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/CorePlugin.php",
        "line": 346,
        "function": "generateMultiStatus",
        "class": "Sabre\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/event/lib/WildcardEmitterTrait.php",
        "line": 89,
        "function": "httpPropFind",
        "class": "Sabre\\DAV\\CorePlugin",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php",
        "line": 472,
        "function": "emit",
        "class": "Sabre\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/Server.php",
        "line": 215,
        "function": "invokeMethod",
        "class": "Sabre\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/apps/dav/lib/Server.php",
        "line": 430,
        "function": "start",
        "class": "OCA\\DAV\\Connector\\Sabre\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/apps/dav/appinfo/v2/remote.php",
        "line": 25,
        "function": "exec",
        "class": "OCA\\DAV\\Server",
        "type": "->"
      },
      {
        "file": "/var/www/nextcloud/master/remote.php",
        "line": 152,
        "args": [
          "/var/www/nextcloud/master/apps/dav/appinfo/v2/remote.php"
        ],
        "function": "require_once"
      }
    ],
    "File": "/var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/DavAclPlugin.php",
    "Line": 58,
    "message": "Calendar with name 'company_shared_by_admin' could not be found",
    "exception": "{\"class\":\"Sabre\\DAV\\Exception\\NotFound\",\"message\":\"Calendar with name 'company_shared_by_admin' could not be found\",\"code\":0,\"file\":\"/var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/DavAclPlugin.php:58\",\"trace\":\"#0 /var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/DavAclPlugin.php(86): OCA\\DAV\\Connector\\Sabre\\DavAclPlugin->checkPrivileges()\\n#1 /var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/Server.php(163): OCA\\DAV\\Connector\\Sabre\\DavAclPlugin->propFind()\\n#2 /var/www/nextcloud/master/3rdparty/sabre/event/lib/WildcardEmitterTrait.php(89): OCA\\DAV\\Connector\\Sabre\\Server->OCA\\DAV\\Connector\\Sabre\\{closure}()\\n#3 /var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php(1052): Sabre\\DAV\\Server->emit()\\n#4 /var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php(984): Sabre\\DAV\\Server->getPropertiesByNode()\\n#5 /var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php(1664): Sabre\\DAV\\Server->getPropertiesIteratorForPath()\\n#6 /var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php(1649): Sabre\\DAV\\Server->writeMultiStatus()\\n#7 /var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/CorePlugin.php(346): Sabre\\DAV\\Server->generateMultiStatus()\\n#8 /var/www/nextcloud/master/3rdparty/sabre/event/lib/WildcardEmitterTrait.php(89): Sabre\\DAV\\CorePlugin->httpPropFind()\\n#9 /var/www/nextcloud/master/3rdparty/sabre/dav/lib/DAV/Server.php(472): Sabre\\DAV\\Server->emit()\\n#10 /var/www/nextcloud/master/apps/dav/lib/Connector/Sabre/Server.php(215): Sabre\\DAV\\Server->invokeMethod()\\n#11 /var/www/nextcloud/master/apps/dav/lib/Server.php(430): OCA\\DAV\\Connector\\Sabre\\Server->start()\\n#12 /var/www/nextcloud/master/apps/dav/appinfo/v2/remote.php(25): OCA\\DAV\\Server->exec()\\n#13 /var/www/nextcloud/master/remote.php(152): require_once('...')\\n#14 {main}\"}",
    "CustomMessage": "Calendar with name 'company_shared_by_admin' could not be found"
  }
}

@GVodyanov

Copy link
Copy Markdown
Contributor Author

I think it's related to nextcloud/server#59232 @hamza221

Tested.

Found error when delegator has a shared calendar

{
  "reqId": "axdoc6W1q46YCrgBbdrq",
  "level": 0,
  "time": "2026-05-07T13:00:21+00:00",

@SebastianKrupinski

Copy link
Copy Markdown
Contributor

Rebased to most recent head

@hamza221 hamza221 added 2. developing Work in progress and removed 3. to review Waiting for reviews labels May 24, 2026
@GVodyanov

Copy link
Copy Markdown
Contributor Author

@hamza221 My bad, ignore my comments

@GVodyanov GVodyanov added 3. to review Waiting for reviews and removed 2. developing Work in progress labels May 24, 2026
@hamza221

Copy link
Copy Markdown
Contributor

Btw sorry for the co-authored commits, I told it to commit as Assisted but apparently it ignored my, will be fixed on squash.

Comment thread src/components/AppNavigation/Settings/SettingsDelegationSection.vue
Comment thread src/store/delegation.js Outdated
Comment thread src/store/delegation.js Outdated
Comment on lines +60 to +62
const baseUrl = currentUser.url.replace(/\/?$/, '')
const proxyWriteGroupUrl = baseUrl + '/calendar-proxy-write'
const proxyReadGroupUrl = baseUrl + '/calendar-proxy-read'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The CDav library should be responsible for creating the specific urls the Calendar app should not need to know how to format a dav url

Comment thread src/store/delegation.js Outdated
Comment thread src/store/delegation.js Outdated
Comment thread src/store/delegation.js Outdated
@SebastianKrupinski

Copy link
Copy Markdown
Contributor

One last comment, this feature needs a version gate for 34 unless we are back porting all the server changes

GVodyanov added a commit that referenced this pull request May 27, 2026
Signed-off-by: Grigory Vodyanov <scratchx@gmx.com>
SebastianKrupinski pushed a commit that referenced this pull request May 27, 2026
Signed-off-by: Grigory Vodyanov <scratchx@gmx.com>
@SebastianKrupinski SebastianKrupinski force-pushed the feat/add-calendar-delegation-features branch from 0c53326 to 74badc4 Compare May 27, 2026 23:30
@SebastianKrupinski

Copy link
Copy Markdown
Contributor

Looks good, I just fixed the linting errors.

This will need to wait until the cdav pr is merged, then the library version will need to be bumped in this pr

SebastianKrupinski pushed a commit that referenced this pull request May 27, 2026
Signed-off-by: Grigory Vodyanov <scratchx@gmx.com>
@SebastianKrupinski SebastianKrupinski force-pushed the feat/add-calendar-delegation-features branch from 74badc4 to 146302e Compare May 27, 2026 23:35
@GVodyanov

Copy link
Copy Markdown
Contributor Author

One last comment, this feature needs a version gate for 34 unless we are back porting all the server changes

Feature gate added

@GVodyanov

Copy link
Copy Markdown
Contributor Author

Thanks a lot for the help Sebastian!

@hamza221

hamza221 commented May 29, 2026

Copy link
Copy Markdown
Contributor

One last comment, this feature needs a version gate for 34 unless we are back porting all the server changes

Feature gate added

No new features were adeed to server, all fixes, all to be backported to 32, no gating actually needed.
ps: just clarifying, I'm okay with the gating if that's the decision, but the feature can work for all Nextcloud versions with the frontend and cdav changes included >=32

Update: should be gated to >=34

GVodyanov added a commit to nextcloud/cdav-library that referenced this pull request May 29, 2026
Signed-off-by: Grigory Vodyanov <scratchx@gmx.com>
@hamza221

hamza221 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

time squash and rebase
CDAV updates are #8403 🚀

Copilot AI 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.

Pull request overview

Adds front-end support for calendar delegation (proxy access) so delegated calendars can be discovered, displayed, and managed in the Calendar UI, gated by Nextcloud version support.

Changes:

  • Introduces a new Pinia delegation store to fetch delegators/delegates and load delegated calendars into the calendars store.
  • Updates Calendar list/pickers/headers to visually distinguish delegated calendars and group them by delegator.
  • Adds a Delegation section to Calendar settings for managing delegates.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
tests/javascript/unit/models/calendar.test.js Updates calendar model expectations for the new delegation-related fields.
src/views/Calendar.vue Loads delegation state (delegators + delegated calendars) when supported.
src/store/principals.js Makes fetchPrincipalByUrl return cached/mapped principals for reuse by delegation UI.
src/store/delegation.ts New store to manage delegates/delegators and ingest delegated calendars.
src/services/caldavService.js Exposes client + adds helper to fetch calendars from an arbitrary calendar-home URL.
src/models/calendar.js Extends calendar model with isDelegated and delegatorUrl.
src/components/Shared/CalendarPickerOption.vue Shows delegated-by label/avatar in calendar picker options.
src/components/Shared/CalendarPicker.vue Passes delegation props through to picker option component.
src/components/Editor/CalendarPickerHeader.vue Shows delegated-by label/avatar in the editor calendar switcher.
src/components/AppointmentConfigModal/DurationInput.vue Removes now-unneeded eslint suppression near emits usage.
src/components/AppNavigation/Settings/SettingsDelegationSection.vue New settings UI to add/revoke delegates with read/write permissions.
src/components/AppNavigation/Settings.vue Adds Delegation settings section behind version gating.
src/components/AppNavigation/CalendarList/CalendarListItem.vue Displays delegated-by details and treats delegated calendars as non-shareable.
src/components/AppNavigation/CalendarList.vue Adds delegated calendars grouping/captions in the navigation list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/store/principals.js
Comment thread src/store/delegation.ts Outdated
Comment thread src/components/AppNavigation/Settings/SettingsDelegationSection.vue
Comment thread src/components/AppNavigation/CalendarList/CalendarListItem.vue
Comment thread tests/javascript/unit/models/calendar.test.js
Comment thread tests/javascript/unit/models/calendar.test.js
Comment thread tests/javascript/unit/models/calendar.test.js
Comment thread tests/javascript/unit/models/calendar.test.js
Comment thread tests/javascript/unit/models/calendar.test.js
Comment thread tests/javascript/unit/models/calendar.test.js
Signed-off-by: Grigory Vodyanov <scratchx@gmx.com>
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>

Assisted-by: claude:Opus 4.7 (1M context)
@hamza221 hamza221 force-pushed the feat/add-calendar-delegation-features branch from 03bc7be to 3fa4240 Compare June 3, 2026 13:05
@hamza221

hamza221 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

fixed ci/ copilot review / squashed and rebased

@GVodyanov GVodyanov merged commit 330d4e9 into main Jun 4, 2026
40 of 41 checks passed
@GVodyanov GVodyanov deleted the feat/add-calendar-delegation-features branch June 4, 2026 12: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 request Feature: Delegation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants