✨(sharing) add shared calendars, remove "agenda" wording
This commit is contained in:
@@ -20,7 +20,8 @@ import { extractCaldavPath } from "./utils";
|
|||||||
export const CalendarList = () => {
|
export const CalendarList = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
davCalendars,
|
ownedCalendars,
|
||||||
|
sharedCalendars,
|
||||||
visibleCalendarUrls,
|
visibleCalendarUrls,
|
||||||
toggleCalendarVisibility,
|
toggleCalendarVisibility,
|
||||||
createCalendar,
|
createCalendar,
|
||||||
@@ -34,6 +35,7 @@ export const CalendarList = () => {
|
|||||||
deleteState,
|
deleteState,
|
||||||
shareModalState,
|
shareModalState,
|
||||||
isMyCalendarsExpanded,
|
isMyCalendarsExpanded,
|
||||||
|
isSharedCalendarsExpanded,
|
||||||
openMenuUrl,
|
openMenuUrl,
|
||||||
handleOpenCreateModal,
|
handleOpenCreateModal,
|
||||||
handleOpenEditModal,
|
handleOpenEditModal,
|
||||||
@@ -47,6 +49,7 @@ export const CalendarList = () => {
|
|||||||
handleMenuToggle,
|
handleMenuToggle,
|
||||||
handleCloseMenu,
|
handleCloseMenu,
|
||||||
handleToggleMyCalendars,
|
handleToggleMyCalendars,
|
||||||
|
handleToggleSharedCalendars,
|
||||||
} = useCalendarListState({
|
} = useCalendarListState({
|
||||||
createCalendar,
|
createCalendar,
|
||||||
updateCalendar,
|
updateCalendar,
|
||||||
@@ -138,7 +141,7 @@ export const CalendarList = () => {
|
|||||||
</div>
|
</div>
|
||||||
{isMyCalendarsExpanded && (
|
{isMyCalendarsExpanded && (
|
||||||
<div className="calendar-list__items">
|
<div className="calendar-list__items">
|
||||||
{davCalendars.map((calendar) => (
|
{ownedCalendars.map((calendar) => (
|
||||||
<CalendarListItem
|
<CalendarListItem
|
||||||
key={calendar.url}
|
key={calendar.url}
|
||||||
calendar={calendar}
|
calendar={calendar}
|
||||||
@@ -157,6 +160,50 @@ export const CalendarList = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{sharedCalendars.length > 0 && (
|
||||||
|
<div className="calendar-list__section">
|
||||||
|
<div className="calendar-list__section-header">
|
||||||
|
<button
|
||||||
|
className="calendar-list__toggle-btn"
|
||||||
|
onClick={handleToggleSharedCalendars}
|
||||||
|
aria-expanded={isSharedCalendarsExpanded}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={`material-icons calendar-list__toggle-icon ${
|
||||||
|
isSharedCalendarsExpanded
|
||||||
|
? 'calendar-list__toggle-icon--expanded'
|
||||||
|
: ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
expand_more
|
||||||
|
</span>
|
||||||
|
<span className="calendar-list__section-title">
|
||||||
|
{t('calendar.list.sharedCalendars')}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{isSharedCalendarsExpanded && (
|
||||||
|
<div className="calendar-list__items">
|
||||||
|
{sharedCalendars.map((calendar) => (
|
||||||
|
<CalendarListItem
|
||||||
|
key={calendar.url}
|
||||||
|
calendar={calendar}
|
||||||
|
isVisible={visibleCalendarUrls.has(calendar.url)}
|
||||||
|
isMenuOpen={openMenuUrl === calendar.url}
|
||||||
|
onToggleVisibility={toggleCalendarVisibility}
|
||||||
|
onMenuToggle={handleMenuToggle}
|
||||||
|
onEdit={handleOpenEditModal}
|
||||||
|
onDelete={handleOpenDeleteModal}
|
||||||
|
onImport={handleOpenImportModal}
|
||||||
|
onSubscription={handleOpenSubscriptionModal}
|
||||||
|
onCloseMenu={handleCloseMenu}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CalendarModal
|
<CalendarModal
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export const useCalendarListState = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [isMyCalendarsExpanded, setIsMyCalendarsExpanded] = useState(true);
|
const [isMyCalendarsExpanded, setIsMyCalendarsExpanded] = useState(true);
|
||||||
|
const [isSharedCalendarsExpanded, setIsSharedCalendarsExpanded] = useState(true);
|
||||||
const [openMenuUrl, setOpenMenuUrl] = useState<string | null>(null);
|
const [openMenuUrl, setOpenMenuUrl] = useState<string | null>(null);
|
||||||
|
|
||||||
// Modal handlers
|
// Modal handlers
|
||||||
@@ -159,6 +160,10 @@ export const useCalendarListState = ({
|
|||||||
setIsMyCalendarsExpanded((prev) => !prev);
|
setIsMyCalendarsExpanded((prev) => !prev);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleToggleSharedCalendars = useCallback(() => {
|
||||||
|
setIsSharedCalendarsExpanded((prev) => !prev);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Modal state
|
// Modal state
|
||||||
modalState,
|
modalState,
|
||||||
@@ -167,6 +172,7 @@ export const useCalendarListState = ({
|
|||||||
|
|
||||||
// Expansion state
|
// Expansion state
|
||||||
isMyCalendarsExpanded,
|
isMyCalendarsExpanded,
|
||||||
|
isSharedCalendarsExpanded,
|
||||||
openMenuUrl,
|
openMenuUrl,
|
||||||
|
|
||||||
// Modal handlers
|
// Modal handlers
|
||||||
@@ -190,5 +196,6 @@ export const useCalendarListState = ({
|
|||||||
|
|
||||||
// Expansion handlers
|
// Expansion handlers
|
||||||
handleToggleMyCalendars,
|
handleToggleMyCalendars,
|
||||||
|
handleToggleSharedCalendars,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ export interface CalendarContextType {
|
|||||||
caldavService: CalDavService;
|
caldavService: CalDavService;
|
||||||
adapter: EventCalendarAdapter;
|
adapter: EventCalendarAdapter;
|
||||||
davCalendars: CalDavCalendar[];
|
davCalendars: CalDavCalendar[];
|
||||||
|
ownedCalendars: CalDavCalendar[];
|
||||||
|
sharedCalendars: CalDavCalendar[];
|
||||||
visibleCalendarUrls: Set<string>;
|
visibleCalendarUrls: Set<string>;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
isConnected: boolean;
|
isConnected: boolean;
|
||||||
@@ -107,6 +109,23 @@ export const CalendarContextProvider = ({
|
|||||||
const [currentDate, setCurrentDate] = useState<Date>(new Date());
|
const [currentDate, setCurrentDate] = useState<Date>(new Date());
|
||||||
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
|
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
|
||||||
|
|
||||||
|
const { ownedCalendars, sharedCalendars } = useMemo(() => {
|
||||||
|
const homeUrl = caldavService.getAccount()?.homeUrl;
|
||||||
|
if (!homeUrl) {
|
||||||
|
return { ownedCalendars: davCalendars, sharedCalendars: [] };
|
||||||
|
}
|
||||||
|
const owned: CalDavCalendar[] = [];
|
||||||
|
const shared: CalDavCalendar[] = [];
|
||||||
|
for (const cal of davCalendars) {
|
||||||
|
if (cal.url.startsWith(homeUrl)) {
|
||||||
|
owned.push(cal);
|
||||||
|
} else {
|
||||||
|
shared.push(cal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { ownedCalendars: owned, sharedCalendars: shared };
|
||||||
|
}, [davCalendars, caldavService]);
|
||||||
|
|
||||||
const refreshCalendars = useCallback(async () => {
|
const refreshCalendars = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@@ -325,6 +344,8 @@ export const CalendarContextProvider = ({
|
|||||||
caldavService,
|
caldavService,
|
||||||
adapter,
|
adapter,
|
||||||
davCalendars,
|
davCalendars,
|
||||||
|
ownedCalendars,
|
||||||
|
sharedCalendars,
|
||||||
visibleCalendarUrls,
|
visibleCalendarUrls,
|
||||||
isLoading,
|
isLoading,
|
||||||
isConnected,
|
isConnected,
|
||||||
|
|||||||
@@ -804,8 +804,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"myCalendars": "Mes agendas",
|
"myCalendars": "Mes calendriers",
|
||||||
"sharedCalendars": "Agendas partagés",
|
"sharedCalendars": "Calendriers partagés",
|
||||||
"shared": "(partagé)",
|
"shared": "(partagé)",
|
||||||
"showCalendar": "Afficher le calendrier",
|
"showCalendar": "Afficher le calendrier",
|
||||||
"edit": "Modifier",
|
"edit": "Modifier",
|
||||||
@@ -906,32 +906,32 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"createCalendar": {
|
"createCalendar": {
|
||||||
"title": "Créer un agenda",
|
"title": "Créer un calendrier",
|
||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"namePlaceholder": "Nom de l'agenda",
|
"namePlaceholder": "Nom du calendrier",
|
||||||
"nameRequired": "Le nom est requis",
|
"nameRequired": "Le nom est requis",
|
||||||
"color": "Couleur",
|
"color": "Couleur",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"descriptionPlaceholder": "Description de l'agenda (optionnel)",
|
"descriptionPlaceholder": "Description du calendrier (optionnel)",
|
||||||
"cancel": "Annuler",
|
"cancel": "Annuler",
|
||||||
"create": "Créer"
|
"create": "Créer"
|
||||||
},
|
},
|
||||||
"editCalendar": {
|
"editCalendar": {
|
||||||
"title": "Modifier l'agenda",
|
"title": "Modifier le calendrier",
|
||||||
"save": "Enregistrer"
|
"save": "Enregistrer"
|
||||||
},
|
},
|
||||||
"deleteCalendar": {
|
"deleteCalendar": {
|
||||||
"title": "Supprimer l'agenda",
|
"title": "Supprimer le calendrier",
|
||||||
"message": "Êtes-vous sûr de vouloir supprimer l'agenda \"{{name}}\" ? Cette action est irréversible.",
|
"message": "Êtes-vous sûr de vouloir supprimer le calendrier \"{{name}}\" ? Cette action est irréversible.",
|
||||||
"confirm": "Supprimer"
|
"confirm": "Supprimer"
|
||||||
},
|
},
|
||||||
"shareCalendar": {
|
"shareCalendar": {
|
||||||
"title": "Partager l'agenda",
|
"title": "Partager le calendrier",
|
||||||
"emailPlaceholder": "Entrez l'adresse email",
|
"emailPlaceholder": "Entrez l'adresse email",
|
||||||
"share": "Partager",
|
"share": "Partager",
|
||||||
"hint": "La personne aura les mêmes droits que vous (lecture et écriture).",
|
"hint": "La personne aura les mêmes droits que vous (lecture et écriture).",
|
||||||
"success": "Agenda partagé avec {{email}}",
|
"success": "Calendrier partagé avec {{email}}",
|
||||||
"error": "Échec du partage de l'agenda",
|
"error": "Échec du partage du calendrier",
|
||||||
"invalidEmail": "Veuillez entrer une adresse email valide"
|
"invalidEmail": "Veuillez entrer une adresse email valide"
|
||||||
},
|
},
|
||||||
"attendees": {
|
"attendees": {
|
||||||
@@ -1109,7 +1109,7 @@
|
|||||||
"event": {
|
"event": {
|
||||||
"createTitle": "Evenement aanmaken",
|
"createTitle": "Evenement aanmaken",
|
||||||
"editTitle": "Evenement bewerken",
|
"editTitle": "Evenement bewerken",
|
||||||
"calendar": "Agenda",
|
"calendar": "Kalender",
|
||||||
"title": "Titel",
|
"title": "Titel",
|
||||||
"titlePlaceholder": "Evenement titel",
|
"titlePlaceholder": "Evenement titel",
|
||||||
"location": "Locatie",
|
"location": "Locatie",
|
||||||
@@ -1178,10 +1178,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"myCalendars": "Mijn agenda's",
|
"myCalendars": "Mijn kalenders",
|
||||||
"sharedCalendars": "Gedeelde agenda's",
|
"sharedCalendars": "Gedeelde kalenders",
|
||||||
"shared": "(gedeeld)",
|
"shared": "(gedeeld)",
|
||||||
"showCalendar": "Agenda tonen",
|
"showCalendar": "Kalender tonen",
|
||||||
"edit": "Bewerken",
|
"edit": "Bewerken",
|
||||||
"delete": "Verwijderen",
|
"delete": "Verwijderen",
|
||||||
"share": "Delen",
|
"share": "Delen",
|
||||||
@@ -1202,21 +1202,21 @@
|
|||||||
"errorDetails": "Foutdetails"
|
"errorDetails": "Foutdetails"
|
||||||
},
|
},
|
||||||
"subscription": {
|
"subscription": {
|
||||||
"title": "Agenda-abonnements-URL",
|
"title": "Kalender-abonnements-URL",
|
||||||
"description": "Gebruik deze URL om u te abonneren op \"{{name}}\" vanuit externe agendatoepassingen (Apple Calendar, Google Calendar, Outlook, etc.).",
|
"description": "Gebruik deze URL om u te abonneren op \"{{name}}\" vanuit externe kalendertoepassingen (Apple Calendar, Google Calendar, Outlook, etc.).",
|
||||||
"loading": "Abonnements-URL wordt gegenereerd...",
|
"loading": "Abonnements-URL wordt gegenereerd...",
|
||||||
"copy": "Kopiëren",
|
"copy": "Kopiëren",
|
||||||
"copied": "Gekopieerd!",
|
"copied": "Gekopieerd!",
|
||||||
"close": "Sluiten",
|
"close": "Sluiten",
|
||||||
"warning": "Deze URL bevat een privétoken. Iedereen met deze link kan uw agenda-evenementen bekijken.",
|
"warning": "Deze URL bevat een privétoken. Iedereen met deze link kan uw kalender-evenementen bekijken.",
|
||||||
"regenerate": "URL regenereren",
|
"regenerate": "URL regenereren",
|
||||||
"regenerateConfirm": {
|
"regenerateConfirm": {
|
||||||
"title": "Abonnements-URL regenereren?",
|
"title": "Abonnements-URL regenereren?",
|
||||||
"message": "Dit maakt de huidige URL ongeldig. Externe agenda's die de oude URL gebruiken zullen niet meer synchroniseren.",
|
"message": "Dit maakt de huidige URL ongeldig. Externe kalenders die de oude URL gebruiken zullen niet meer synchroniseren.",
|
||||||
"confirm": "Regenereren"
|
"confirm": "Regenereren"
|
||||||
},
|
},
|
||||||
"error": "Genereren van abonnements-URL mislukt. Probeer het opnieuw.",
|
"error": "Genereren van abonnements-URL mislukt. Probeer het opnieuw.",
|
||||||
"errorPermission": "U heeft geen toegang tot deze agenda.",
|
"errorPermission": "U heeft geen toegang tot deze kalender.",
|
||||||
"errorNetwork": "Netwerkfout. Controleer uw verbinding en probeer het opnieuw.",
|
"errorNetwork": "Netwerkfout. Controleer uw verbinding en probeer het opnieuw.",
|
||||||
"errorServer": "Serverfout. Probeer het later opnieuw."
|
"errorServer": "Serverfout. Probeer het later opnieuw."
|
||||||
},
|
},
|
||||||
@@ -1280,32 +1280,32 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"createCalendar": {
|
"createCalendar": {
|
||||||
"title": "Agenda aanmaken",
|
"title": "Kalender aanmaken",
|
||||||
"name": "Naam",
|
"name": "Naam",
|
||||||
"namePlaceholder": "Agenda naam",
|
"namePlaceholder": "Kalender naam",
|
||||||
"nameRequired": "Naam is verplicht",
|
"nameRequired": "Naam is verplicht",
|
||||||
"color": "Kleur",
|
"color": "Kleur",
|
||||||
"description": "Beschrijving",
|
"description": "Beschrijving",
|
||||||
"descriptionPlaceholder": "Agenda beschrijving (optioneel)",
|
"descriptionPlaceholder": "Kalender beschrijving (optioneel)",
|
||||||
"cancel": "Annuleren",
|
"cancel": "Annuleren",
|
||||||
"create": "Aanmaken"
|
"create": "Aanmaken"
|
||||||
},
|
},
|
||||||
"editCalendar": {
|
"editCalendar": {
|
||||||
"title": "Agenda bewerken",
|
"title": "Kalender bewerken",
|
||||||
"save": "Opslaan"
|
"save": "Opslaan"
|
||||||
},
|
},
|
||||||
"deleteCalendar": {
|
"deleteCalendar": {
|
||||||
"title": "Agenda verwijderen",
|
"title": "Kalender verwijderen",
|
||||||
"message": "Weet u zeker dat u de agenda \"{{name}}\" wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
|
"message": "Weet u zeker dat u de kalender \"{{name}}\" wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
|
||||||
"confirm": "Verwijderen"
|
"confirm": "Verwijderen"
|
||||||
},
|
},
|
||||||
"shareCalendar": {
|
"shareCalendar": {
|
||||||
"title": "Agenda delen",
|
"title": "Kalender delen",
|
||||||
"emailPlaceholder": "Voer e-mailadres in",
|
"emailPlaceholder": "Voer e-mailadres in",
|
||||||
"share": "Delen",
|
"share": "Delen",
|
||||||
"hint": "De persoon krijgt dezelfde rechten als u (lezen en schrijven).",
|
"hint": "De persoon krijgt dezelfde rechten als u (lezen en schrijven).",
|
||||||
"success": "Agenda gedeeld met {{email}}",
|
"success": "Kalender gedeeld met {{email}}",
|
||||||
"error": "Delen van agenda mislukt",
|
"error": "Delen van kalender mislukt",
|
||||||
"invalidEmail": "Voer een geldig e-mailadres in"
|
"invalidEmail": "Voer een geldig e-mailadres in"
|
||||||
},
|
},
|
||||||
"attendees": {
|
"attendees": {
|
||||||
|
|||||||
Reference in New Issue
Block a user