added dev env

Signed-off-by: Alex Rybchenko <arybchenko@box.com>
This commit is contained in:
Alex Rybchenko
2022-02-25 15:52:15 +01:00
parent 9297424748
commit a4b4cf5ede
19 changed files with 3087 additions and 3903 deletions
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { OAuthApi, createApiRef, FetchApi } from '@backstage/core-plugin-api';
import { GCalendar, GCalendarEvent } from './types';
import { ResponseError } from '@backstage/errors';
type Options = {
authApi: OAuthApi;
fetchApi: FetchApi;
};
export const gcalendarApiRef = createApiRef<GCalendarApiClient>({
id: 'plugin.gcalendar.service',
});
export class GCalendarApiClient {
private readonly authApi: OAuthApi;
private readonly fetchApi: FetchApi;
constructor(options: Options) {
this.authApi = options.authApi;
this.fetchApi = options.fetchApi;
}
private async get<T>(
path: string,
params: { [key in string]: any },
): Promise<T> {
const query = new URLSearchParams(params);
const url = new URL(
`${path}?${query.toString()}`,
'https://www.googleapis.com',
);
const token = await this.authApi.getAccessToken();
const response = await this.fetchApi.fetch(url.toString(), {
headers: token ? { Authorization: `Bearer ${token}` } : {},
});
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return response.json() as Promise<T>;
}
public async getCalendars(params?: any) {
return this.get<{ items: GCalendar[] }>(
'/calendar/v3/users/me/calendarList',
params,
);
}
public async getEvents(calendarId: string, params?: any) {
return this.get<{ items: GCalendarEvent[] }>(
`/calendar/v3/calendars/${encodeURIComponent(calendarId)}/events`,
params,
);
}
}
+2 -58
View File
@@ -13,61 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { OAuthApi, createApiRef, FetchApi } from '@backstage/core-plugin-api';
import { GCalendar, GCalendarEvent } from '../components/CalendarCard/types';
import { ResponseError } from '@backstage/errors';
type Options = {
authApi: OAuthApi;
fetchApi: FetchApi;
};
export const gcalendarApiRef = createApiRef<GCalendarApiClient>({
id: 'plugin.gcalendar.service',
});
export class GCalendarApiClient {
private readonly authApi: OAuthApi;
private readonly fetchApi: FetchApi;
constructor(options: Options) {
this.authApi = options.authApi;
this.fetchApi = options.fetchApi;
}
private async get<T>(
path: string,
params: { [key in string]: any },
): Promise<T> {
const query = new URLSearchParams(params);
const url = new URL(
`${path}?${query.toString()}`,
'https://www.googleapis.com',
);
const token = await this.authApi.getAccessToken();
const response = await this.fetchApi.fetch(url.toString(), {
headers: token ? { Authorization: `Bearer ${token}` } : {},
});
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return response.json() as Promise<T>;
}
public async getCalendars(params?: any) {
return this.get<{ items: GCalendar[] }>(
'/calendar/v3/users/me/calendarList',
params,
);
}
public async getEvents(calendarId: string, params?: any) {
return this.get<{ items: GCalendarEvent[] }>(
`/calendar/v3/calendars/${encodeURIComponent(calendarId)}/events`,
params,
);
}
}
export * from './client';
export * from './types';
@@ -18,7 +18,7 @@ import React from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { AttendeeChip } from './AttendeeChip';
import { EventAttendee, ResponseStatus } from './types';
import { EventAttendee, ResponseStatus } from '../../api';
describe('<AttendeeChip />', () => {
it('renders attendee email', async () => {
@@ -21,7 +21,7 @@ import { Badge, Chip, makeStyles } from '@material-ui/core';
import CancelIcon from '@material-ui/icons/Cancel';
import CheckIcon from '@material-ui/icons/CheckCircle';
import { EventAttendee, ResponseStatus } from './types';
import { EventAttendee, ResponseStatus } from '../../api';
const useStyles = makeStyles((theme: BackstageTheme) => {
const getIconColor = (responseStatus?: string) => {
@@ -35,46 +35,51 @@ import {
import zoomIcon from '../../icons/zoomIcon.svg';
import { CalendarEventPopoverContent } from './CalendarEventPopoverContent';
import { GCalendarEvent, ResponseStatus } from './types';
import { GCalendarEvent, ResponseStatus } from '../../api';
import { getTimePeriod, getZoomLink, isAllDay, isPassed } from './util';
const useStyles = makeStyles(theme => ({
event: {
display: 'flex',
alignItems: 'center',
marginBottom: theme.spacing(1),
cursor: 'pointer',
paddingRight: 12,
},
declined: {
textDecoration: 'line-through',
},
passed: {
opacity: 0.6,
transition: 'opacity 0.15s ease-in-out',
'&:hover': {
opacity: 1,
const useStyles = makeStyles(
theme => ({
event: {
display: 'flex',
alignItems: 'center',
marginBottom: theme.spacing(1),
cursor: 'pointer',
paddingRight: 12,
},
},
link: {
width: 48,
height: 48,
display: 'inline-block',
padding: 8,
borderRadius: '50%',
'&:hover': {
backgroundColor: theme.palette.grey[100],
declined: {
textDecoration: 'line-through',
},
},
calendarColor: ({ event }: any) => ({
width: 8,
borderTopLeftRadius: 4,
borderBottomLeftRadius: 4,
backgroundColor: event.primary
? theme.palette.primary.light
: event.backgroundColor,
passed: {
opacity: 0.6,
transition: 'opacity 0.15s ease-in-out',
'&:hover': {
opacity: 1,
},
},
link: {
width: 48,
height: 48,
display: 'inline-block',
padding: 8,
borderRadius: '50%',
'&:hover': {
backgroundColor: theme.palette.grey[100],
},
},
calendarColor: ({ event }: { event: GCalendarEvent }) => ({
width: 8,
borderTopLeftRadius: 4,
borderBottomLeftRadius: 4,
backgroundColor: event.primary
? theme.palette.primary.light
: event.backgroundColor,
}),
}),
}));
{
name: 'GCalendarEvent',
},
);
export const CalendarEvent = ({ event }: { event: GCalendarEvent }) => {
const classes = useStyles({ event });
@@ -31,24 +31,29 @@ import {
import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
import { AttendeeChip } from './AttendeeChip';
import { GCalendarEvent } from './types';
import { GCalendarEvent } from '../../api';
import { getTimePeriod, getZoomLink } from './util';
const useStyles = makeStyles(theme => {
return {
description: {
wordBreak: 'break-word',
'& a': {
color: theme.palette.primary.main,
fontWeight: 500,
const useStyles = makeStyles(
theme => {
return {
description: {
wordBreak: 'break-word',
'& a': {
color: theme.palette.primary.main,
fontWeight: 500,
},
},
},
divider: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
},
};
});
divider: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
},
};
},
{
name: 'GCalendarEventPopoverContent',
},
);
type CalendarEventPopoverProps = {
event: GCalendarEvent;
@@ -27,17 +27,22 @@ import {
makeStyles,
} from '@material-ui/core';
import { GCalendar } from './types';
import { GCalendar } from '../../api';
const useStyles = makeStyles({
formControl: {
width: 120,
const useStyles = makeStyles(
{
formControl: {
width: 120,
},
selectedCalendars: {
textOverflow: 'ellipsis',
overflow: 'hidden',
},
},
selectedCalendars: {
textOverflow: 'ellipsis',
overflow: 'hidden',
{
name: 'GCalendarSelect',
},
});
);
type CalendarSelectProps = {
disabled: boolean;
@@ -18,10 +18,12 @@ import React from 'react';
import { Box, Button, styled } from '@material-ui/core';
import { CalendarEvent } from './CalendarEvent';
import { events } from './signInEventMock';
import { eventsMock } from './signInEventMock';
import { GCalendarEvent } from '../..';
type SignInContentProps = {
type Props = {
handleAuthClick: React.MouseEventHandler<HTMLElement>;
events?: GCalendarEvent[];
};
const TransparentBox = styled(Box)({
@@ -29,7 +31,10 @@ const TransparentBox = styled(Box)({
filter: 'blur(1.5px)',
});
export const SignInContent = ({ handleAuthClick }: SignInContentProps) => {
export const SignInContent = ({
handleAuthClick,
events = eventsMock,
}: Props) => {
return (
<Box position="relative" height="100%" width="100%">
<TransparentBox p={1}>
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { GCalendarEvent } from './types';
import { GCalendarEvent } from '../../api';
export const events: GCalendarEvent[] = [
export const eventsMock: GCalendarEvent[] = [
{
id: '1',
htmlLink: 'https://www.google.com/calendar/',
@@ -15,7 +15,7 @@
*/
import { DateTime } from 'luxon';
import { GCalendarEvent } from './types';
import { GCalendarEvent } from '../../api';
export function getZoomLink(event: GCalendarEvent) {
const videoEntrypoint = event.conferenceData?.entryPoints?.find(
@@ -20,7 +20,7 @@ import { useQueries } from 'react-query';
import { useApi } from '@backstage/core-plugin-api';
import { gcalendarApiRef } from '../api';
import { GCalendar, GCalendarEvent } from '../components/CalendarCard/types';
import { GCalendar, GCalendarEvent } from '../api';
type Options = {
selectedCalendars?: string[];
+1 -1
View File
@@ -15,7 +15,7 @@
*/
import { gcalendarPlugin } from './plugin';
describe('gcalendar-homepage', () => {
describe('gcalendar', () => {
it('should export plugin', () => {
expect(gcalendarPlugin).toBeDefined();
});
+1 -1
View File
@@ -25,7 +25,7 @@ import { GCalendarApiClient, gcalendarApiRef } from './api';
import { rootRouteRef } from './routes';
export const gcalendarPlugin = createPlugin({
id: 'gcalendar-homepage',
id: 'gcalendar',
routes: {
root: rootRouteRef,
},
+1 -1
View File
@@ -16,5 +16,5 @@
import { createRouteRef } from '@backstage/core-plugin-api';
export const rootRouteRef = createRouteRef({
id: 'gcalendar-homepage',
id: 'gcalendar',
});