diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2ca7ebc5..b5a4b977 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,7 +45,6 @@ jobs: # Build the documentation. - name: Build docs env: - GOOGLE_CALENDAR_ID: ${{ secrets.GOOGLE_CALENDAR_ID }} GOOGLE_CALENDAR_API_KEY: ${{ secrets.GOOGLE_CALENDAR_API_KEY }} run: sphinx-build -b=html docs/ build/ diff --git a/docs/demo/kitchen-sink/calendar.rst b/docs/demo/kitchen-sink/calendar.rst index 2956810b..f0fe9713 100644 --- a/docs/demo/kitchen-sink/calendar.rst +++ b/docs/demo/kitchen-sink/calendar.rst @@ -3,24 +3,26 @@ Calendar ======== The napari calendar is an HTML element you can include anywhere using the -``napari-calendar`` directive: +``calendar`` directive: .. code-block:: rst - .. napari-calendar:: + .. calendar:: + :calendar-id: c_35r93ec6vtp8smhm7dv5uot0v4@group.calendar.google.com To use the calendar, you'll need to find out the calendar ID of the calendar you want to use, and create a Google Calendar API token: https://console.developers.google.com/flows/enableapi?apiid=calendar -Next, you'll need to pass the calendar ID and API key to the Sphinx build -process as environment variables: +Next, you'll need to pass the API key to the Sphinx build process as environment +variables: .. code-block:: sh - GOOGLE_CALENDAR_ID=calendar-id GOOGLE_CALENDAR_API_KEY=api-key sphinx-build -b=html docs/ dist/ + GOOGLE_CALENDAR_API_KEY=api-key sphinx-build -b=html docs/ dist/ -.. napari-calendar:: +.. calendar:: + :calendar-id: c_35r93ec6vtp8smhm7dv5uot0v4@group.calendar.google.com ------- Filters @@ -32,8 +34,10 @@ meetings, but in the future we could make it configurable. .. code-block:: rst - .. napari-calendar:: + .. calendar:: + :calendar-id: c_35r93ec6vtp8smhm7dv5uot0v4@group.calendar.google.com :show-filters: .. napari-calendar:: + :calendar-id: c_35r93ec6vtp8smhm7dv5uot0v4@group.calendar.google.com :show-filters: diff --git a/src/napari_sphinx_theme/__init__.py b/src/napari_sphinx_theme/__init__.py index 0c04432b..5b39bf87 100644 --- a/src/napari_sphinx_theme/__init__.py +++ b/src/napari_sphinx_theme/__init__.py @@ -507,7 +507,6 @@ def get_edit_url(): # ----------------------------------------------------------------------------- -GOOGLE_CALENDAR_ID = os.environ.get('GOOGLE_CALENDAR_ID', '') GOOGLE_CALENDAR_API_KEY = os.environ.get('GOOGLE_CALENDAR_API_KEY', '') def add_google_calendar_secrets(app, exception): @@ -523,7 +522,6 @@ def add_google_calendar_secrets(app, exception): with open(script_path, 'r') as f: source = f.read() - source = source.replace('{google_calendar_id}', GOOGLE_CALENDAR_ID) source = source.replace('{google_calendar_api_key}', GOOGLE_CALENDAR_API_KEY) with open(script_path, 'w') as f: @@ -548,7 +546,7 @@ def setup(app): app.connect("html-page-context", update_templates) app.connect("build-finished", add_google_calendar_secrets) - app.add_directive('napari-calendar', CalendarDirective) + app.add_directive('calendar', CalendarDirective) # Include templates for sidebar app.config.templates_path.append(str(theme_path / "_templates")) diff --git a/src/napari_sphinx_theme/assets/components/Calendar/Calendar.tsx b/src/napari_sphinx_theme/assets/components/Calendar/Calendar.tsx index d6bb14f2..ca5a2346 100644 --- a/src/napari_sphinx_theme/assets/components/Calendar/Calendar.tsx +++ b/src/napari_sphinx_theme/assets/components/Calendar/Calendar.tsx @@ -7,6 +7,7 @@ import { CalendarProvider } from './context'; import { CopyCalendarButton } from './CopyCalendarButton'; interface Props { + calendarID: string; filter?: boolean; } @@ -17,15 +18,13 @@ interface Props { * For screens smaller than 900px, a week view is rendered with events for the * current week. Otherwise, a month view is used. */ -export function Calendar({ filter }: Props) { +export function Calendar({ calendarID, filter }: Props) { return (
- +
Copy to calendar diff --git a/src/napari_sphinx_theme/assets/components/Calendar/CalendarTile.tsx b/src/napari_sphinx_theme/assets/components/Calendar/CalendarTile.tsx index 14e070a5..6c7f48c7 100644 --- a/src/napari_sphinx_theme/assets/components/Calendar/CalendarTile.tsx +++ b/src/napari_sphinx_theme/assets/components/Calendar/CalendarTile.tsx @@ -51,7 +51,7 @@ export function CalendarTile({ date }: Props) {
    {eventList.map((event) => ( (null); interface Props { + calendarID: string; children: ReactNode; } /** * Provider that shares global state within the Calendar component tree. */ -export function CalendarProvider({ children }: Props) { +export function CalendarProvider({ calendarID, children }: Props) { const calendarState = useConstant(() => proxy({ activeStartDate: dayjs(), @@ -68,7 +69,7 @@ export function CalendarProvider({ children }: Props) { ); // Fetch calendar events when the active month changes. - useFetchCalendarEvents(calendarState); + useFetchCalendarEvents(calendarID, calendarState); const calendarContext = useMemo( () => ({ diff --git a/src/napari_sphinx_theme/assets/components/Calendar/gapi.ts b/src/napari_sphinx_theme/assets/components/Calendar/gapi.ts index 15e0a44a..3a9cc5f5 100644 --- a/src/napari_sphinx_theme/assets/components/Calendar/gapi.ts +++ b/src/napari_sphinx_theme/assets/components/Calendar/gapi.ts @@ -93,6 +93,7 @@ export async function fetchEvents( start, title, type, + id: event.id, description: event.description, htmlLink: event.htmlLink, location: event.location ?? '', diff --git a/src/napari_sphinx_theme/assets/components/Calendar/types.ts b/src/napari_sphinx_theme/assets/components/Calendar/types.ts index 6e617e52..75dcaac8 100644 --- a/src/napari_sphinx_theme/assets/components/Calendar/types.ts +++ b/src/napari_sphinx_theme/assets/components/Calendar/types.ts @@ -3,6 +3,7 @@ import type { Dayjs } from 'dayjs'; export type MeetingType = 'community' | 'workingGroup' | 'other'; export interface CalendarEvent { + id: string; calendarId: string; description: string; end: Dayjs; diff --git a/src/napari_sphinx_theme/assets/components/Calendar/useFetchCalendarEvents.ts b/src/napari_sphinx_theme/assets/components/Calendar/useFetchCalendarEvents.ts index 76b75990..db3ec5e2 100644 --- a/src/napari_sphinx_theme/assets/components/Calendar/useFetchCalendarEvents.ts +++ b/src/napari_sphinx_theme/assets/components/Calendar/useFetchCalendarEvents.ts @@ -10,10 +10,11 @@ import { CalendarState } from './types'; /** * Effect for fetching the calendar event state when the user changes the * current month. - * - * @param calendarState The shard calendar state. */ -export function useFetchCalendarEvents(calendarState: CalendarState): void { +export function useFetchCalendarEvents( + calendarID: string, + calendarState: CalendarState, +): void { const { activeStartDate } = useSnapshot(calendarState); const prevActiveStartDate = usePrevious(activeStartDate); @@ -34,10 +35,7 @@ export function useFetchCalendarEvents(calendarState: CalendarState): void { await maybeLoadCalendarAPI(process.env.GOOGLE_CALENDAR_API_KEY ?? ''); - calendarState.events = await fetchEvents( - process.env.GOOGLE_CALENDAR_ID ?? '', - activeStartDate, - ); + calendarState.events = await fetchEvents(calendarID, activeStartDate); } // Wrapper without `async` so that we can call it like a normal function @@ -49,5 +47,5 @@ export function useFetchCalendarEvents(calendarState: CalendarState): void { // Fetch events on initial load. fetchCalendarEvents(); - }, [activeStartDate, calendarState, prevActiveStartDate]); + }, [activeStartDate, calendarID, calendarState, prevActiveStartDate]); } diff --git a/src/napari_sphinx_theme/assets/napari.tsx b/src/napari_sphinx_theme/assets/napari.tsx index fef9285d..73aa7e6f 100644 --- a/src/napari_sphinx_theme/assets/napari.tsx +++ b/src/napari_sphinx_theme/assets/napari.tsx @@ -340,14 +340,27 @@ function renderCalendars() { document.querySelectorAll('.napari-calendar'), ); - calendarNodes.forEach((node) => - render( - - - , - node, - ), - ); + calendarNodes.forEach((node) => { + const calendarID = Array.from(node.classList) + .map((className) => + className.startsWith('calendar-id') + ? className.split('calendar-id-')[1] + : undefined, + ) + .find(Boolean); + + if (calendarID) { + render( + + + , + node, + ); + } + }); } function fixSearchInput() { diff --git a/src/napari_sphinx_theme/calendar.py b/src/napari_sphinx_theme/calendar.py index 0fc431a3..11353d4f 100644 --- a/src/napari_sphinx_theme/calendar.py +++ b/src/napari_sphinx_theme/calendar.py @@ -8,10 +8,16 @@ class CalendarDirective(SphinxDirective): has_content = True option_spec: OptionSpec = { 'show-filters': directives.flag, + 'calendar-id': directives.unchanged_required, } def run(self) -> List[nodes.Node]: - classes = ['napari-calendar'] + classes = [ + 'napari-calendar', + # Hacky approach to pass calendar ID to div since it's not possible to + # pass HTML attributes using docutils :( + f'calendar-id-{self.options["calendar-id"]}', + ] if 'show-filters' in self.options: classes.append('show-filters') diff --git a/webpack.config.js b/webpack.config.js index f8293576..a0e7de5c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -67,7 +67,6 @@ const config = { new webpack.EnvironmentPlugin({ ENV: process.env.ENV || 'local', GOOGLE_CALENDAR_API_KEY: '{google_calendar_api_key}', - GOOGLE_CALENDAR_ID: '{google_calendar_id}', NODE_ENV: env, }), ],