mirror of
https://github.com/ae-utbm/sith.git
synced 2025-04-16 02:50:22 +00:00
Merge pull request #1070 from ae-utbm/calendar-link
Remote calendar link for external sync
This commit is contained in:
commit
11efa4fca2
@ -1,9 +1,11 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import final
|
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
from django.contrib.syndication.views import add_domain
|
||||||
from django.db.models import F, QuerySet
|
from django.db.models import F, QuerySet
|
||||||
|
from django.http import HttpRequest
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from ical.calendar import Calendar
|
from ical.calendar import Calendar
|
||||||
@ -14,7 +16,14 @@ from com.models import NewsDate
|
|||||||
from core.models import User
|
from core.models import User
|
||||||
|
|
||||||
|
|
||||||
@final
|
def as_absolute_url(url: str, request: HttpRequest | None = None) -> str:
|
||||||
|
return add_domain(
|
||||||
|
Site.objects.get_current(request=request),
|
||||||
|
url,
|
||||||
|
secure=request.is_secure() if request is not None else settings.HTTPS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class IcsCalendar:
|
class IcsCalendar:
|
||||||
_CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars"
|
_CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars"
|
||||||
_INTERNAL_CALENDAR = _CACHE_FOLDER / "internal.ics"
|
_INTERNAL_CALENDAR = _CACHE_FOLDER / "internal.ics"
|
||||||
@ -58,7 +67,9 @@ class IcsCalendar:
|
|||||||
summary=news_date.news_title,
|
summary=news_date.news_title,
|
||||||
start=news_date.start_date,
|
start=news_date.start_date,
|
||||||
end=news_date.end_date,
|
end=news_date.end_date,
|
||||||
url=reverse("com:news_detail", kwargs={"news_id": news_date.news.id}),
|
url=as_absolute_url(
|
||||||
|
reverse("com:news_detail", kwargs={"news_id": news_date.news.id})
|
||||||
|
),
|
||||||
)
|
)
|
||||||
calendar.events.append(event)
|
calendar.events.append(event)
|
||||||
|
|
||||||
|
@ -44,7 +44,18 @@ export class IcsCalendar extends inheritHtmlElement("div") {
|
|||||||
return this.isMobile() ? "listMonth" : "dayGridMonth";
|
return this.isMobile() ? "listMonth" : "dayGridMonth";
|
||||||
}
|
}
|
||||||
|
|
||||||
currentToolbar() {
|
currentFooterToolbar() {
|
||||||
|
if (this.isMobile()) {
|
||||||
|
return {
|
||||||
|
start: "",
|
||||||
|
center: "getCalendarLink",
|
||||||
|
end: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { start: "getCalendarLink", center: "", end: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
currentHeaderToolbar() {
|
||||||
if (this.isMobile()) {
|
if (this.isMobile()) {
|
||||||
return {
|
return {
|
||||||
left: "prev,next",
|
left: "prev,next",
|
||||||
@ -303,14 +314,44 @@ export class IcsCalendar extends inheritHtmlElement("div") {
|
|||||||
this.calendar = new Calendar(this.node, {
|
this.calendar = new Calendar(this.node, {
|
||||||
plugins: [dayGridPlugin, iCalendarPlugin, listPlugin],
|
plugins: [dayGridPlugin, iCalendarPlugin, listPlugin],
|
||||||
locales: [frLocale, enLocale],
|
locales: [frLocale, enLocale],
|
||||||
|
customButtons: {
|
||||||
|
getCalendarLink: {
|
||||||
|
text: gettext("Copy calendar link"),
|
||||||
|
click: async (event: Event) => {
|
||||||
|
const button = event.target as HTMLButtonElement;
|
||||||
|
button.classList.add("text-copy");
|
||||||
|
if (!button.hasAttribute("position")) {
|
||||||
|
button.setAttribute("tooltip", gettext("Link copied"));
|
||||||
|
button.setAttribute("position", "top");
|
||||||
|
button.setAttribute("no-hover", "");
|
||||||
|
}
|
||||||
|
if (button.classList.contains("text-copied")) {
|
||||||
|
button.classList.remove("text-copied");
|
||||||
|
}
|
||||||
|
navigator.clipboard.writeText(
|
||||||
|
new URL(
|
||||||
|
await makeUrl(calendarCalendarInternal),
|
||||||
|
window.location.origin,
|
||||||
|
).toString(),
|
||||||
|
);
|
||||||
|
setTimeout(() => {
|
||||||
|
button.classList.remove("text-copied");
|
||||||
|
button.classList.add("text-copied");
|
||||||
|
button.classList.remove("text-copy");
|
||||||
|
}, 1500);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
height: "auto",
|
height: "auto",
|
||||||
locale: this.locale,
|
locale: this.locale,
|
||||||
initialView: this.currentView(),
|
initialView: this.currentView(),
|
||||||
headerToolbar: this.currentToolbar(),
|
headerToolbar: this.currentHeaderToolbar(),
|
||||||
|
footerToolbar: this.currentFooterToolbar(),
|
||||||
eventSources: await this.getEventSources(),
|
eventSources: await this.getEventSources(),
|
||||||
windowResize: () => {
|
windowResize: () => {
|
||||||
this.calendar.changeView(this.currentView());
|
this.calendar.changeView(this.currentView());
|
||||||
this.calendar.setOption("headerToolbar", this.currentToolbar());
|
this.calendar.setOption("headerToolbar", this.currentHeaderToolbar());
|
||||||
|
this.calendar.setOption("footerToolbar", this.currentFooterToolbar());
|
||||||
},
|
},
|
||||||
eventClick: (event) => {
|
eventClick: (event) => {
|
||||||
// Avoid our popup to be deleted because we clicked outside of it
|
// Avoid our popup to be deleted because we clicked outside of it
|
||||||
|
@ -98,4 +98,26 @@ ics-calendar {
|
|||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fc .fc-toolbar.fc-footer-toolbar {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.text-copy,
|
||||||
|
button.text-copy:focus,
|
||||||
|
button.text-copy:hover {
|
||||||
|
background-color: #67AE6E !important;
|
||||||
|
transition: 500ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.text-copied,
|
||||||
|
button.text-copied:focus,
|
||||||
|
button.text-copied:hover {
|
||||||
|
transition: 500ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.text-copied[tooltip]::before {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 500ms ease-out;
|
||||||
|
}
|
||||||
}
|
}
|
@ -51,24 +51,55 @@ body {
|
|||||||
|
|
||||||
[tooltip]::before {
|
[tooltip]::before {
|
||||||
@include shadow;
|
@include shadow;
|
||||||
opacity: 0;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
content: attr(tooltip);
|
content: attr(tooltip);
|
||||||
background: hsl(219.6, 20.8%, 96%);
|
left: 50%;
|
||||||
color: $black-color;
|
transform: translateX(-50%);
|
||||||
|
background-color: #333;
|
||||||
|
color: #fff;
|
||||||
border: 0.5px solid hsl(0, 0%, 50%);
|
border: 0.5px solid hsl(0, 0%, 50%);
|
||||||
;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 5px;
|
padding: 5px 10px;
|
||||||
top: 1em;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 5px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
opacity: 0;
|
||||||
transition: opacity 500ms ease-out;
|
transition: opacity 500ms ease-out;
|
||||||
|
top: 120%; // Put the tooltip under the element
|
||||||
}
|
}
|
||||||
|
|
||||||
[tooltip]:hover::before {
|
[tooltip]:hover::before {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
transition: opacity 500ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
[no-hover][tooltip]::before {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 500ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
[position="top"][tooltip]::before {
|
||||||
|
top: initial;
|
||||||
|
bottom: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
|
[position="bottom"][tooltip]::before {
|
||||||
|
top: 120%;
|
||||||
|
bottom: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
[position="left"][tooltip]::before {
|
||||||
|
top: initial;
|
||||||
|
bottom: 0%;
|
||||||
|
left: initial;
|
||||||
|
right: 65%;
|
||||||
|
}
|
||||||
|
|
||||||
|
[position="right"][tooltip]::before {
|
||||||
|
top: initial;
|
||||||
|
bottom: 0%;
|
||||||
|
left: 150%;
|
||||||
|
right: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ib {
|
.ib {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-06 15:47+0200\n"
|
"POT-Creation-Date: 2025-04-08 11:42+0200\n"
|
||||||
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
||||||
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -33,6 +33,14 @@ msgstr "Dépublier"
|
|||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr "Supprimer"
|
msgstr "Supprimer"
|
||||||
|
|
||||||
|
#: com/static/bundled/com/components/ics-calendar-index.ts
|
||||||
|
msgid "Copy calendar link"
|
||||||
|
msgstr "Copier le lien du calendrier"
|
||||||
|
|
||||||
|
#: com/static/bundled/com/components/ics-calendar-index.ts
|
||||||
|
msgid "Link copied"
|
||||||
|
msgstr "Lien copié"
|
||||||
|
|
||||||
#: com/static/bundled/com/components/moderation-alert-index.ts
|
#: com/static/bundled/com/components/moderation-alert-index.ts
|
||||||
#, javascript-format
|
#, javascript-format
|
||||||
msgid ""
|
msgid ""
|
||||||
|
@ -78,10 +78,12 @@ DEBUG = env.bool("SITH_DEBUG", default=False)
|
|||||||
TESTING = "pytest" in sys.modules
|
TESTING = "pytest" in sys.modules
|
||||||
INTERNAL_IPS = ["127.0.0.1"]
|
INTERNAL_IPS = ["127.0.0.1"]
|
||||||
|
|
||||||
|
HTTPS = env.bool("HTTPS", default=True)
|
||||||
|
|
||||||
# force csrf tokens and cookies to be secure when in https
|
# force csrf tokens and cookies to be secure when in https
|
||||||
CSRF_COOKIE_SECURE = env.bool("HTTPS", default=True)
|
CSRF_COOKIE_SECURE = HTTPS
|
||||||
CSRF_TRUSTED_ORIGINS = env.list("CSRF_TRUSTED_ORIGINS", default=[])
|
CSRF_TRUSTED_ORIGINS = env.list("CSRF_TRUSTED_ORIGINS", default=[])
|
||||||
SESSION_COOKIE_SECURE = env.bool("HTTPS", default=True)
|
SESSION_COOKIE_SECURE = HTTPS
|
||||||
X_FRAME_OPTIONS = "SAMEORIGIN"
|
X_FRAME_OPTIONS = "SAMEORIGIN"
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["*"]
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user