Closed sumnerevans closed 2 years ago
Just found a small project, which works with Nextcloud: https://github.com/samjaninf/appointment-planer
Some possible requirements:
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:
@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 :)
Here is an example of how Outlook does it on mobile, starting in Mail:
@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.
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.
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:
This is for the recipient:
I might have clients that would be able to chip in for this feature.
@jancborchardt now you have screenshots from pipedrive (which works like calendly)
A good thing would be if you could setup several different links with different type of slots.
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 im going to check if they would like to add to it :)
Can this be closed and continued at https://github.com/SergeyMosin/Appointments
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.
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.
@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>
...
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.
@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.
@SergeyMosin That would still require largely refactoring your app, so it's using the CalDAV interface via javascript, right?
Generally speaking, this is also a feature i would like to see directly in the calendar app, not in the 3rdparty app.
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.
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
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.
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
Hi @jospoortvliet , just a heads up that there's no bounty on this on bountysource's website here
@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:
Yep, quite possibly
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 ;-)
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
Add new database structure for slots and their preferences. This includes
Design-wise, this is how Google now does it since the Workspace update:
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.
Some polishing
Edit view:
Overview page:
[ ] Make the appointment as a button with the grey area. It would be nice to have boxes around the appointment like in dashboard.
[ ] Lets remove the arrow on the right, and use the event icon on all of them.
[ ] The name should be in bold and h2 and desc not bold. Add text "Book an appointment with {{name}}"
Booking page(select date, select slot):
[ ] It should start at the first possible date for an appointment (by the config). Despite any booking conflicts. If no slots, it should show a text why theres no slots.
[ ] Make the days before today not active.
[ ] Show only the possible days (available days).
[ ] The avatar is small make it double the size.
[ ] When theres no slots the container its a bit far down. Give it a bit of bottom padding.
[ ] The slots should be sticky and we should only scroll them when its too long(low priority)
[ ] Fix the jumb for the timezone.
When you click a time(hour)
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"
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:
Add navigation bar (to be done when we have more element on the modal)In the future have the save button as stickyMake availability section collapsible (if we have a component for this)we don'tOverview page:
[x] #3623
[x] #3644
[x] #3642
Booking page(select date, select slot):
[x] It should start at the first possible date for an appointment (by the config). Despite any booking conflicts. https://github.com/nextcloud/calendar/pull/3631
[x] #3725
[x] Show only the possible days (available days) https://github.com/nextcloud/calendar/pull/3631
[x] #3641
[x] #3726
[x]
The slots should be sticky and we should only scroll them when its too long(low priority)[x] #3654
When you click a time(hour)
Possible enhancements in the future
3479
3480
Original request