nextcloud / calendar

📆 Calendar app for Nextcloud
https://apps.nextcloud.com/apps/calendar
GNU Affero General Public License v3.0
984 stars 241 forks source link

Appointments support #1023

Closed sumnerevans closed 2 years ago

sumnerevans commented 5 years ago

As a user I want to define appointment slots where someone can book a meeting with me.

Basics

Planned improvements

Design Review Details

Some polishing

Edit view:

Overview page:

When you click a time(hour)

Possible enhancements in the future


Original request

Google Calendar for Business has a feature where you can set up "Appointment Slots". It works as follows: Create an event on a calendar, and select the "Appointment slots" option. You can configure the slots to have a certain duration, or be a single slot. See screenshot: ![2018-12-23-15 19 07](https://user-images.githubusercontent.com/16734772/50387962-2543c380-06c6-11e9-9bf5-9257e647a0db.png) Then, you can share a link to the calendar where people can book time on your calendar in those appointment slots: ![2018-12-23-15 20 24](https://user-images.githubusercontent.com/16734772/50387969-59b77f80-06c6-11e9-8f96-76e6de496ba8.png) I would like this feature in Nextcloud. I know that the calendar is backed by CalDAV and I have a feeling that this is not an actual feature of CalDav, so it would require some significant changes to the calendar app itself, or possibly not even be part of the calendar app at all? Is this a feature that would be welcome in the default Nextcloud calendar? If so, I am willing to help implement it (I will need guidance though, I have no familiarity with developing Nextcloud apps).
dgsiegel commented 5 years ago

Just found a small project, which works with Nextcloud: https://github.com/samjaninf/appointment-planer

georgehrke commented 5 years ago

Some possible requirements:

Freebusy and selfbooking module

The idea of this module is to enable my customers to do booking of appointments with me (the operator of the cloud) on their own. For that

To do so, that module has to run on the cloud server and needs to provide two web interfaces:

The result should be a browser interpretable calendar view, which can be integrated to a web page - as well as CalDAV client readable output.

Config interface needs at least these controls:

User interface therefore needs these entries:

jancborchardt commented 5 years ago

@dgsiegel is this issue basically what is similar to Calendly? If you can share any screenshots of the Calendly flow or how you use it, that would be great :)

jancborchardt commented 5 years ago

Here is an example of how Outlook does it on mobile, starting in Mail: outlook mobile availability flow

dgsiegel commented 5 years ago

@dgsiegel is this issue basically what is similar to Calendly? If you can share any screenshots of the Calendly flow or how you use it, that would be great :)

Yes, that's about right. Ideally, instead of sending out an invite I could send a link, where people not registered on my Nextcloud instance can select a time and date for a meeting.

sumnerevans commented 5 years ago

I haven't really used Calendy, but from my understanding, it dosen't seem like Calendy has as much control over which blocks of time are available for people to book.

A lot of times I don't want people to be able to book my time, even if I don't have an official event on my calendar (for example, maybe that is my "get in the flow" time, and I don't want that to necessarily be on my calendar, but I don't want people to book appointments in the middle of it). I couldn't figure out how to do that in Calendy, which is why I ended up using Google Calendar instead.

nolens commented 4 years ago

I have placed a 250 USD bounty on this. Expiring in 6 months. Bountysource Anyone?

small1 commented 4 years ago

I have missed this bug. I got thinking about this last year. Being able to assign a subset of slots from the calendar and the recipient can choose by himself on what to use. It is used in a few CRM apps for sales people to book appointments

Here is screenshots from pipedrive. One of the options is to schedule fixed slots.

These are for my calendar and creating a visible slot: Screenshot from 2020-01-27 11-41-43 Screenshot from 2020-01-27 11-41-29 Screenshot from 2020-01-27 11-40-42 Screenshot from 2020-01-27 11-40-31 Screenshot from 2020-01-27 11-40-21

This is for the recipient: Screenshot from 2020-01-27 11-42-34

small1 commented 4 years ago

I might have clients that would be able to chip in for this feature.

small1 commented 4 years ago

@jancborchardt now you have screenshots from pipedrive (which works like calendly)

small1 commented 4 years ago

A good thing would be if you could setup several different links with different type of slots.

georgehrke commented 4 years ago

Let me repost something from another ticket here so it doesn't get lost: It's best if we tackle this issue incrementally:

Once those two things are implemented, adding slot support will be much easier.

nolens commented 4 years ago

I might have clients that would be able to chip in for this feature.

@small1 : They might want to add on my bounty - or claim it? ;=) Bountysource

small1 commented 4 years ago

@nolens im going to check if they would like to add to it :)

SergeyMosin commented 4 years ago

Can this be closed and continued at https://github.com/SergeyMosin/Appointments

georgehrke commented 4 years ago

As long as your app is relying on private APIs and might hence break with any update of Nextcloud, I cannot accept it as a solution.

If we want to implement this properly, using only public supported APIs, there is no way around implementing the server changes i discussed further above.

kiwy42 commented 4 years ago

I know it's not a solution integrated with Nextcloud and it will probably take time to achieve a production ready solution. But open source project such as https://github.com/alextselegidis/easyappointments could help to get some inspiration. I would really like to see such tool integrated to Nextcloud.

SergeyMosin commented 4 years ago

@georgehrke RE: public supported APIs

NC public APIs do not support creating/updating events from public pages, however this can be done without private APIs via sabre/dav plugin and \Sabre\CalDAV\Backend\BackendInterface (https://github.com/nextcloud/3rdparty/blob/a70e51b4cce278e006090d91cf26d616cb73e911/sabre/dav/lib/CalDAV/Backend/BackendInterface.php#L6) interface, which is public and well documented.

info.xml:

...
    <sabre>
        <plugins>
            <plugin>OCA\Appointments\SabrePlugin</plugin>
        </plugins>
        <collections>
            <collection>OCA\Appointments\SabreCollection</collection>
        </collections>
    </sabre>
...

ref: https://github.com/nextcloud/server/blob/dc0ee357a42763738cb13d368b25c1b94619cbca/apps/dav/lib/Server.php#L304

SabrePlugin.php

...
$this->server = $server;
$server->on('method:GET', function(RequestInterface $request, ResponseInterface $response) {

    $url = $request->getPath();
    if(strpos($url,"appointments")===0){

        $user=$this->getUserFromPath($url);

        /** @var \OCA\DAV\CalDAV\CalendarHome */
        $calendarHome=$this->server->tree->getNodeForPath('calendars/'.$user);

        if($calendarHome instanceof \OCA\DAV\CalDAV\CalendarHome) {

            /** @var \Sabre\CalDAV\Backend\BackendInterface */
            $backend = $calendarHome->getCalDAVBackend();

            if($backend instanceof \Sabre\CalDAV\Backend\BackendInterface){

                \OC::$server->getLogger()->debug(var_export(
                    $backend->getCalendarsForUser('principals/users/'.$user),
                    true));
//              $backend->updateCalendarObject(...)
//              ...
            }
        }
    }
});
...

This way my app would not directly use your private APIs (unless you are planing to get rid of sabre).

If implemented this way, does this resolve the "Private API" issue ?

This would be so much easier if the BackendInterface would be exposed somewhere, maybe in ICalendar perhaps.

SergeyMosin commented 4 years ago

@georgehrke Public APIs - New Plan:

I can actually just set up an authentication backend for requests from my public form page as per https://github.com/nextcloud/server/blob/dc0ee357a42763738cb13d368b25c1b94619cbca/apps/dav/lib/Server.php#L115 and then just send AJAX requests directly to ...remote.php/dav/calendars/... before the form is submitted.

This solution uses zero private APIs and once implemented should satisfy the "no private APIs" requirement. Please confirm.

georgehrke commented 4 years ago

@SergeyMosin That would still require largely refactoring your app, so it's using the CalDAV interface via javascript, right?

georgehrke commented 4 years ago

Generally speaking, this is also a feature i would like to see directly in the calendar app, not in the 3rdparty app.

tcitworld commented 4 years ago

I want to push for basic write support in OCP instead so that we avoid this kind of issues (Polls app also would be interested, and probably many more).

Generally speaking, this is also a feature i would like to see directly in the calendar app, not in the 3rdparty app.

I would like this as well, but I feel like we wouldn't want to have as much as features and options @SergeyMosin app has.

georgehrke commented 4 years ago

I want to push for basic write support in OCP instead so that we avoid this kind of issues (Polls app also would be interested, and probably many more).

I'm totally in favour of adding write-support for \OCP\Calendar as well, but that will require us to break our current simple event format. It just takes the first VEVENT block and turns it into a simple key-value array. So it doesn't support calendar-objects with multiple events (like recurrence-exceptions, etc.)

Let me create a tech-debt ticket in the server for that: https://github.com/nextcloud/server/issues/20154

SergeyMosin commented 4 years ago

That would still require largely refactoring your app, so it's using the CalDAV interface via javascript, right?

Yes, it would become some sort of hybrid of two sabre plugins (one for custom auth from public pages and one for updating calendar objects) and the nextcloud frontend.

georgehrke commented 4 years ago

Let me create a tech-debt ticket in the server for that. Will link it later.

Here we go: https://github.com/nextcloud/server/issues/20154

brymut commented 4 years ago

Hi @jospoortvliet , just a heads up that there's no bounty on this on bountysource's website here

georgehrke commented 4 years ago

@brymut I believe it was a six-month limited bounty, but I'm not 100% sure. The bounty source website does not provide much information about it: E5C464B8-2D31-42FA-B605-7678D0ECCCFC

brymut commented 4 years ago

Yep, quite possibly

jospoortvliet commented 4 years ago

Sorry guys, I have no idea how this works exactly... These changes are done by a bot using my account so I actually am clueless ;-)

ChristophWurst commented 3 years ago

We are planning a possible integration of this feature right inside Nextcloud Calendar.

For reference we looked into some of the commercial solutions as well as @SergeyMosin's app.

The way I imagine this feature in Calendar is that we might not directly need/use https://github.com/nextcloud/server/issues/3509 because I think there should be some logic that ensures users are only inserting events to slots that are bookable by the appointments logic and not write at arbitrary times. This way a user's personal calendar stays protected from malicious action when they chose that calendar to be the destination for booked slots.

For the configured slots I'd say it's best if we store the rules and preferences in our database and then only show them on the calendar grid as something like a "virtual" calendar that doesn't actually exist on DAV, because right now I don't think one needs a DAV calendar with all available but not yet booked slots.

I'm also unsure if we really need https://github.com/nextcloud/server/issues/11214. The reasoning is that we can likely do this query internally like @SergeyMosin did if I understand the app's code correctly. We just have to see how doable that is when we want to keep the API usage clean.

All in all this seems like from an architectural perspective the browser window that books an appointment would not directly interact with DAV, but only with dedicated APIs of Calendar. The Calendar APIs then use the slot information from its own DB in combination with the user's calendar data via Sabre to do the free/blocked handling. Data will be written back through Sabre or a OCP API. The Calendar front-end fetches the slots from an API as well and shows them similar to real calendars (but likely some distinct design/icons).

End of brain dump :v:

Edit: here are some first technical details on how this could be done conceptually

Additional data stored in Calendar

Slot configurations

Add new database structure for slots and their preferences. This includes

jancborchardt commented 3 years ago

Design-wise, this is how Google now does it since the Workspace update:

miaulalala commented 3 years ago

So, short explanation of the way the logic currently works:

Appointment Config:

Sets the different parameters, such as name, start time, end time, increment, preparation time etc which will be used to generate slots later. The RRule allows more sophisticated configuration, such as days of the week etc.

Booking: 1) Slots are defined via an RRule. 2) We generate all possible slots within the constraints set by the RRule. 3) The max amount of bookable slots per week is generated 4) The slots are then intersected with one or more calendars to remove any unavailable times.

Related PRs are https://github.com/nextcloud/server/pull/29188 and https://github.com/nextcloud/server/pull/28970

I'll add more documentation as I go.

GretaD commented 3 years ago

Some polishing

Edit view:

Overview page:

When you click a time(hour)

miaulalala commented 3 years ago

Also please change the default options for the (greyed out) preparation and follow up duration to 0 Minutes. Firstly, 0 minutes to be sent should be fine anyway, secondly, having 5 minutes as default, even when it's greyed out could be confused to mean "always have at least 5 minutes of prep / follow up"

miaulalala commented 3 years ago