- rename from jitsi_calendar to atocal, to reflect more the usage. This plugin allows to create events
- add initial documentation
This commit is contained in:
1 parent
8c5d19375e
commit
b100d9c986
6 files changed
+118
-38
No files matched your search
@@ -0,0 +1,80 @@
|
||||
# AToCal — Add To Calendar
|
||||
|
||||
A Nextcloud app that lets remote applications create events in the
|
||||
authenticated user's Nextcloud Calendar via a simple link.
|
||||
|
||||
## How it works
|
||||
|
||||
```
|
||||
remote app Nextcloud (atocal)
|
||||
| |
|
||||
| GET /apps/atocal/confirm |
|
||||
| summary, start, end, ... |
|
||||
|----------------------------->|
|
||||
| | confirm page
|
||||
|<-----------------------------|
|
||||
| |
|
||||
| POST /apps/atocal/create | (CSRF token from form)
|
||||
|----------------------------->|
|
||||
| | event in "Personal" calendar
|
||||
|<-----------------------------| redirect to Calendar app
|
||||
```
|
||||
|
||||
The remote app links the user to the confirm page. The user reviews
|
||||
the event and submits the form. The event lands in the user's
|
||||
"Personal" calendar and the browser opens the Calendar app.
|
||||
|
||||
## Routes
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|--------|------|---------|
|
||||
| GET | `/apps/atocal/confirm` | Show confirmation page |
|
||||
| POST | `/apps/atocal/create` | Create the event |
|
||||
|
||||
## Link parameters (GET `/confirm` and form POST `/create`)
|
||||
|
||||
| Parameter | Required | Rules |
|
||||
|-----------|----------|-------|
|
||||
| `summary` | yes | max 255 chars |
|
||||
| `start` | yes | datetime-local, e.g. `2026-10-07T14:15` |
|
||||
| `end` | yes | after `start`, same format |
|
||||
| `description` | no | max 10000 chars |
|
||||
| `location` | no | HTTPS URL |
|
||||
| `url` | no | HTTPS URL; merged into description |
|
||||
| `organizer` | no | email address |
|
||||
|
||||
Dates carry no timezone and are interpreted in the user's Nextcloud
|
||||
timezone (server default as fallback).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
https://cloud.example.com/apps/atocal/confirm?summary=Kickoff&start=2026-10-12T10:00&end=2026-10-12T11:00&location=https%3A%2F%2Fmeet.example.com%2Fkickoff
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Nextcloud 34 or 35
|
||||
- Calendar app enabled
|
||||
- A writable calendar named "Personal"
|
||||
(event creation fails with a friendly error otherwise)
|
||||
|
||||
## Install
|
||||
|
||||
Copy this directory to the Nextcloud server as
|
||||
`custom_apps/atocal`, then:
|
||||
|
||||
```
|
||||
occ app:enable atocal
|
||||
```
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
appinfo/info.xml app metadata
|
||||
appinfo/routes.php routes
|
||||
lib/AppInfo/Application.php container setup
|
||||
lib/Controller/CalendarController.php confirm/create logic
|
||||
templates/confirm.php confirmation page
|
||||
templates/style.css page styles
|
||||
```
|
||||
+5
-5
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<info xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
|
||||
<id>jitsi_calendar</id>
|
||||
<name>Jitsi Calendar</name>
|
||||
<summary>Create Jitsi meetings in the user's Nextcloud Calendar</summary>
|
||||
<id>atocal</id>
|
||||
<name>Add To Calendar</name>
|
||||
<summary>Create events in the user's Nextcloud Calendar</summary>
|
||||
<description>
|
||||
Allows the Jitsi meeting launcher to create calendar events in the authenticated user's Nextcloud Calendar.
|
||||
Allows remote applications to create calendar events in the authenticated user's Nextcloud Calendar.
|
||||
</description>
|
||||
<version>1.0.0</version>
|
||||
<licence>AGPL</licence>
|
||||
<author>Stefan Tollkühn s.tollkuehn@bnvb-ingenieure.de</author>
|
||||
<namespace>JitsiCalendar</namespace>
|
||||
<namespace>AToCal</namespace>
|
||||
<category>integration</category>
|
||||
<dependencies>
|
||||
<nextcloud min-version="34" max-version="35"/>
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\JitsiCalendar\AppInfo;
|
||||
namespace OCA\AToCal\AppInfo;
|
||||
|
||||
use OCA\JitsiCalendar\Controller\CalendarController;
|
||||
use OCA\AToCal\Controller\CalendarController;
|
||||
use OCP\AppFramework\App;
|
||||
use OCP\AppFramework\IAppContainer;
|
||||
|
||||
class Application extends App
|
||||
{
|
||||
public const APP_ID = 'jitsi_calendar';
|
||||
public const APP_ID = 'atocal';
|
||||
|
||||
public function __construct(array $urlParams = [])
|
||||
{
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\JitsiCalendar\Controller;
|
||||
namespace OCA\AToCal\Controller;
|
||||
|
||||
use OCA\JitsiCalendar\AppInfo\Application;
|
||||
use OCA\AToCal\AppInfo\Application;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
|
||||
+13
-13
@@ -12,34 +12,34 @@ $h = static function (string $value): string {
|
||||
?>
|
||||
|
||||
<div id="app-content">
|
||||
<div class="jitsi-calendar-container">
|
||||
<div class="atocal-container">
|
||||
|
||||
<div class="jitsi-calendar-card">
|
||||
<div class="atocal-card">
|
||||
|
||||
<h1>
|
||||
Add Jitsi Meeting to Calendar
|
||||
Add To Calendar
|
||||
</h1>
|
||||
|
||||
<p class="jitsi-calendar-intro">
|
||||
<p class="atocal-intro">
|
||||
The following meeting will be added to your
|
||||
Nextcloud Calendar.
|
||||
</p>
|
||||
|
||||
<?php if ($_['error'] !== ''): ?>
|
||||
<div class="jitsi-calendar-error">
|
||||
<div class="atocal-error">
|
||||
<?= $h($_['error']) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="jitsi-calendar-details">
|
||||
<div class="atocal-details">
|
||||
|
||||
<div class="jitsi-calendar-row">
|
||||
<div class="atocal-row">
|
||||
<strong>Title</strong>
|
||||
<span><?= $h($_['summary']) ?></span>
|
||||
</div>
|
||||
|
||||
<?php if ($_['description'] !== ''): ?>
|
||||
<div class="jitsi-calendar-row">
|
||||
<div class="atocal-row">
|
||||
<strong>Description</strong>
|
||||
<span class="description">
|
||||
<?= nl2br($h($_['description'])) ?>
|
||||
@@ -47,25 +47,25 @@ $h = static function (string $value): string {
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="jitsi-calendar-row">
|
||||
<div class="atocal-row">
|
||||
<strong>Start</strong>
|
||||
<span><?= $h(str_replace('T', ' ', $_['start'])) ?></span>
|
||||
</div>
|
||||
|
||||
<div class="jitsi-calendar-row">
|
||||
<div class="atocal-row">
|
||||
<strong>End</strong>
|
||||
<span><?= $h(str_replace('T', ' ', $_['end'])) ?></span>
|
||||
</div>
|
||||
|
||||
<?php if ($_['organizer'] !== ''): ?>
|
||||
<div class="jitsi-calendar-row">
|
||||
<div class="atocal-row">
|
||||
<strong>Organizer</strong>
|
||||
<span><?= $h($_['organizer']) ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($_['location'] !== ''): ?>
|
||||
<div class="jitsi-calendar-row">
|
||||
<div class="atocal-row">
|
||||
<strong>Location</strong>
|
||||
<span>
|
||||
<a
|
||||
@@ -133,7 +133,7 @@ $h = static function (string $value): string {
|
||||
value="<?= $h($_['url']) ?>"
|
||||
>
|
||||
|
||||
<div class="jitsi-calendar-actions">
|
||||
<div class="atocal-actions">
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
|
||||
+15
-15
@@ -1,10 +1,10 @@
|
||||
.jitsi-calendar-container {
|
||||
.atocal-container {
|
||||
max-width: 760px;
|
||||
margin: 60px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.jitsi-calendar-card {
|
||||
.atocal-card {
|
||||
background: var(--color-main-background);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 12px;
|
||||
@@ -12,17 +12,17 @@
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.jitsi-calendar-card h1 {
|
||||
.atocal-card h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.jitsi-calendar-intro {
|
||||
.atocal-intro {
|
||||
color: var(--color-text-maxcontrast);
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.jitsi-calendar-error {
|
||||
.atocal-error {
|
||||
background: var(--color-error);
|
||||
color: var(--color-error-text);
|
||||
border-radius: 6px;
|
||||
@@ -30,13 +30,13 @@
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.jitsi-calendar-details {
|
||||
.atocal-details {
|
||||
border-top: 1px solid var(--color-border);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.jitsi-calendar-row {
|
||||
.atocal-row {
|
||||
display: grid;
|
||||
grid-template-columns: 150px 1fr;
|
||||
gap: 16px;
|
||||
@@ -44,26 +44,26 @@
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.jitsi-calendar-row:last-child {
|
||||
.atocal-row:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.jitsi-calendar-row span {
|
||||
.atocal-row span {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.jitsi-calendar-row .description {
|
||||
.atocal-row .description {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.jitsi-calendar-actions {
|
||||
.atocal-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.jitsi-calendar-actions button,
|
||||
.jitsi-calendar-actions a {
|
||||
.atocal-actions button,
|
||||
.atocal-actions a {
|
||||
display: inline-block;
|
||||
padding: 10px 18px;
|
||||
border-radius: 6px;
|
||||
@@ -71,13 +71,13 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jitsi-calendar-actions button.primary {
|
||||
.atocal-actions button.primary {
|
||||
background: var(--color-primary-element);
|
||||
color: var(--color-primary-element-text);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.jitsi-calendar-actions a.secondary {
|
||||
.atocal-actions a.secondary {
|
||||
border: 1px solid var(--color-border);
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
Reference in new issue
Block a user