Skip to content

Commit

Permalink
Calendar updates (#116)
Browse files Browse the repository at this point in the history
* Make calendar ID a directive option

* Fix CalendarTile key error for duplicate events lol
  • Loading branch information
codemonkey800 authored Jul 12, 2022
1 parent ee920b2 commit d20b56e
Show file tree
Hide file tree
Showing 12 changed files with 56 additions and 37 deletions.
1 change: 0 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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/

Expand Down
18 changes: 11 additions & 7 deletions docs/demo/kitchen-sink/calendar.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
4 changes: 1 addition & 3 deletions src/napari_sphinx_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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:
Expand All @@ -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"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CalendarProvider } from './context';
import { CopyCalendarButton } from './CopyCalendarButton';

interface Props {
calendarID: string;
filter?: boolean;
}

Expand All @@ -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 (
<div className="tw-flex tw-flex-col tw-flex-1 tw-items-stretch">
<CalendarProvider>
<CalendarProvider calendarID={calendarID}>
<div>
<CopyCalendarButton
href={`https://calendar.google.com/calendar/u/0/r?cid=${
process.env.GOOGLE_CALENDAR_ID ?? ''
}`}
href={`https://calendar.google.com/calendar/u/0/r?cid=${calendarID}`}
>
Copy to calendar
</CopyCalendarButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function CalendarTile({ date }: Props) {
<ul className="tw-flex tw-flex-col tw-space-y-1 tw-m-0 tw-p-0">
{eventList.map((event) => (
<CalendarEventButton
key={event.title + event.start.toString()}
key={event.id}
date={dayjs(event.start)}
event={event}
width={tileWidth}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ interface CalendarContextValue {
const CalenderContext = createContext<CalendarContextValue | null>(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<CalendarState>({
activeStartDate: dayjs(),
Expand Down Expand Up @@ -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(
() => ({
Expand Down
1 change: 1 addition & 0 deletions src/napari_sphinx_theme/assets/components/Calendar/gapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export async function fetchEvents(
start,
title,
type,
id: event.id,
description: event.description,
htmlLink: event.htmlLink,
location: event.location ?? '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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
Expand All @@ -49,5 +47,5 @@ export function useFetchCalendarEvents(calendarState: CalendarState): void {

// Fetch events on initial load.
fetchCalendarEvents();
}, [activeStartDate, calendarState, prevActiveStartDate]);
}, [activeStartDate, calendarID, calendarState, prevActiveStartDate]);
}
29 changes: 21 additions & 8 deletions src/napari_sphinx_theme/assets/napari.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -340,14 +340,27 @@ function renderCalendars() {
document.querySelectorAll('.napari-calendar'),
);

calendarNodes.forEach((node) =>
render(
<MaterialUIProvider>
<Calendar filter={node.classList.contains('show-filters')} />
</MaterialUIProvider>,
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(
<MaterialUIProvider>
<Calendar
calendarID={calendarID}
filter={node.classList.contains('show-filters')}
/>
</MaterialUIProvider>,
node,
);
}
});
}

function fixSearchInput() {
Expand Down
8 changes: 7 additions & 1 deletion src/napari_sphinx_theme/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
1 change: 0 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}),
],
Expand Down

0 comments on commit d20b56e

Please sign in to comment.