diff --git a/packages/core/src/layout/Sidebar/PinButton.tsx b/packages/core/src/layout/Sidebar/PinButton.tsx deleted file mode 100644 index 8c52eeb24d..0000000000 --- a/packages/core/src/layout/Sidebar/PinButton.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 React, { FC, useContext } from 'react'; -import { makeStyles } from '@material-ui/core'; -import DoubleArrowIcon from '@material-ui/icons/DoubleArrow'; -import { SidebarContext } from './config'; -import { BackstageTheme } from '@backstage/theme'; -import { SidebarPinStateContext } from './Page'; - -const ARROW_BUTTON_SIZE = 20; -const useStyles = makeStyles(theme => { - return { - root: { - position: 'relative', - alignSelf: 'stretch', - }, - arrowButtonWrapper: { - position: 'absolute', - right: 0, - width: ARROW_BUTTON_SIZE, - height: ARROW_BUTTON_SIZE, - top: -(theme.spacing(6) + ARROW_BUTTON_SIZE) / 2, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - borderRadius: '2px 0px 0px 2px', - background: theme.palette.pinSidebarButton.background, - color: theme.palette.pinSidebarButton.icon, - border: 'none', - outline: 'none', - cursor: 'pointer', - }, - arrowButtonIcon: { - transform: ({ isPinned }) => (isPinned ? 'rotate(180deg)' : 'none'), - }, - }; -}); - -export const SidebarPinButton: FC<{}> = () => { - const { isOpen } = useContext(SidebarContext); - const { isPinned, toggleSidebarPinState } = useContext( - SidebarPinStateContext, - ); - const classes = useStyles({ isPinned }); - - return ( -
- {isOpen && ( - - )} -
- ); -}; diff --git a/packages/core/src/layout/Sidebar/Settings/PinButton.tsx b/packages/core/src/layout/Sidebar/Settings/PinButton.tsx new file mode 100644 index 0000000000..dcd0818ad6 --- /dev/null +++ b/packages/core/src/layout/Sidebar/Settings/PinButton.tsx @@ -0,0 +1,64 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React, { useContext } from 'react'; +import { + ListItem, + ListItemSecondaryAction, + ListItemText, + Tooltip, +} from '@material-ui/core'; +import LockIcon from '@material-ui/icons/Lock'; +import LockOpenIcon from '@material-ui/icons/LockOpen'; +import { ToggleButton } from '@material-ui/lab'; +import { SidebarPinStateContext } from '../Page'; + +export const SidebarPinButton = () => { + const { isPinned, toggleSidebarPinState } = useContext( + SidebarPinStateContext, + ); + + const PinIcon = () => ( + + {isPinned ? : } + + ); + + return ( + + + + { + toggleSidebarPinState(); + }} + > + + + + + ); +}; diff --git a/packages/core/src/layout/Sidebar/Settings/ProviderSettingsItem.tsx b/packages/core/src/layout/Sidebar/Settings/ProviderSettingsItem.tsx index 3d3d7439e1..653c64575b 100644 --- a/packages/core/src/layout/Sidebar/Settings/ProviderSettingsItem.tsx +++ b/packages/core/src/layout/Sidebar/Settings/ProviderSettingsItem.tsx @@ -14,31 +14,53 @@ * limitations under the License. */ -import React, { FC } from 'react'; -import { OAuthApi, OpenIdConnectApi, IconComponent } from '@backstage/core-api'; -import { SidebarItem } from '../Items'; -import { IconButton, Tooltip } from '@material-ui/core'; -import StarBorder from '@material-ui/icons/StarBorder'; +import React from 'react'; +import { IconComponent, OAuthApi, OpenIdConnectApi } from '@backstage/core-api'; +import { + ListItem, + ListItemIcon, + ListItemSecondaryAction, + ListItemText, + Tooltip, +} from '@material-ui/core'; import PowerButton from '@material-ui/icons/PowerSettingsNew'; +import { ToggleButton } from '@material-ui/lab'; -export const ProviderSettingsItem: FC<{ +type Props = { title: string; icon: IconComponent; signedIn: boolean; api: OAuthApi | OpenIdConnectApi; signInHandler: Function; -}> = ({ title, icon, signedIn, api, signInHandler }) => { - return ( - - (signedIn ? api.logout() : signInHandler())}> +}; + +export const ProviderSettingsItem = ({ + title, + icon: Icon, + signedIn, + api, + signInHandler, +}: Props) => ( + + + + + + + (signedIn ? api.logout() : signInHandler())} + > - + - - - ); -}; + + + +); diff --git a/packages/core/src/layout/Sidebar/Settings/SettingsDialog.tsx b/packages/core/src/layout/Sidebar/Settings/SettingsDialog.tsx new file mode 100644 index 0000000000..b37053763b --- /dev/null +++ b/packages/core/src/layout/Sidebar/Settings/SettingsDialog.tsx @@ -0,0 +1,70 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React from 'react'; +import { + Card, + CardContent, + CardHeader, + Divider, + makeStyles, +} from '@material-ui/core'; +import List from '@material-ui/core/List'; +import ListSubheader from '@material-ui/core/ListSubheader'; +import { SidebarPinButton } from './PinButton'; +import { SignInAvatar } from './SignInAvatar'; +import { SidebarThemeToggle } from './ThemeToggle'; +import { UserSettingsMenu } from './UserSettingsMenu'; +import { useUserProfile } from './useUserProfileInfo'; + +const useStyles = makeStyles({ + root: { + minWidth: 400, + }, +}); + +export const SettingsDialog = ({ + providerSettings, +}: { + providerSettings?: React.ReactNode; +}) => { + const classes = useStyles(); + const { profile, displayName } = useUserProfile(); + + return ( + + } + action={} + title={displayName} + subheader={profile.email} + /> + + + App Settings}> + + + + + Available Auth Providers} + > + {providerSettings} + + + + ); +}; diff --git a/packages/core/src/layout/Sidebar/Settings/SignInAvatar.tsx b/packages/core/src/layout/Sidebar/Settings/SignInAvatar.tsx new file mode 100644 index 0000000000..c6eed74a18 --- /dev/null +++ b/packages/core/src/layout/Sidebar/Settings/SignInAvatar.tsx @@ -0,0 +1,63 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React from 'react'; +import { BackstageTheme } from '@backstage/theme'; +import { makeStyles, Avatar } from '@material-ui/core'; +import { useUserProfile } from './useUserProfileInfo'; + +// const useStyles = makeStyles({ +// avatar: { +// width: ({ size }) => size, +// height: ({ size }) => size, +// }, +// }); + +// export const SignInAvatar = ({ size = 24 }: { size?: number }) => { +// const classes = useStyles({ size }); +// const { profile, displayName } = useUserProfile(); + +// return ( +// +// {displayName[0]} +// +// ); +// }; + +// const useStyles = makeStyles({ +// avatar: { +// width: 24, +// height: 24, +// }, +// }); + +const useStyles = makeStyles({ + avatar: { + width: 24, + height: 24, + }, +}); + +export const SignInAvatar = () => { + const classes = useStyles(); + const { profile, displayName } = useUserProfile(); + + return ( + + {displayName[0]} + + ); +}; diff --git a/packages/core/src/layout/Sidebar/Settings/ThemeToggle.tsx b/packages/core/src/layout/Sidebar/Settings/ThemeToggle.tsx new file mode 100644 index 0000000000..29cfb24885 --- /dev/null +++ b/packages/core/src/layout/Sidebar/Settings/ThemeToggle.tsx @@ -0,0 +1,87 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React from 'react'; +import { useObservable } from 'react-use'; +import LightIcon from '@material-ui/icons/WbSunny'; +import DarkIcon from '@material-ui/icons/Brightness2'; +import AutoIcon from '@material-ui/icons/BrightnessAuto'; +import { appThemeApiRef, useApi } from '@backstage/core-api'; +import ToggleButton from '@material-ui/lab/ToggleButton'; +import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup'; +import { + ListItem, + ListItemText, + ListItemSecondaryAction, + Tooltip, +} from '@material-ui/core'; + +export const SidebarThemeToggle = () => { + const appThemeApi = useApi(appThemeApiRef); + const themeId = useObservable( + appThemeApi.activeThemeId$(), + appThemeApi.getActiveThemeId(), + ); + + const themeIds = appThemeApi.getInstalledThemes(); + // TODO: can these be put on the theme itself? + const themeIcons = { + dark: , + light: , + }; + + const handleSetTheme = ( + _event: React.MouseEvent, + newThemeId: string | undefined, + ) => { + if (themeIds.some(t => t.id === newThemeId)) { + appThemeApi.setActiveThemeId(newThemeId); + } else { + appThemeApi.setActiveThemeId(undefined); + } + }; + + return ( + + + + + {themeIds.map(theme => ( + + + {themeIcons[theme.variant]} + + + ))} + + + + + + + + + ); +}; diff --git a/packages/core/src/layout/Sidebar/Settings/UserProfile.tsx b/packages/core/src/layout/Sidebar/Settings/UserProfile.tsx deleted file mode 100644 index 3b854801c9..0000000000 --- a/packages/core/src/layout/Sidebar/Settings/UserProfile.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 React, { FC, useRef } from 'react'; -import { makeStyles, Avatar, Divider } from '@material-ui/core'; -import { useApi, identityApiRef } from '@backstage/core-api'; -import { SidebarItem } from '../Items'; -import ExpandLess from '@material-ui/icons/ExpandLess'; -import ExpandMore from '@material-ui/icons/ExpandMore'; - -const useStyles = makeStyles({ - avatar: { - width: 24, - height: 24, - }, -}); - -export const UserProfile: FC<{ open: boolean; setOpen: Function }> = ({ - open, - setOpen, -}) => { - const ref = useRef(); // for scrolling down when collapse item opens - const classes = useStyles(); - const identityApi = useApi(identityApiRef); - - const handleClick = () => { - setOpen(!open); - setTimeout(() => ref.current?.scrollIntoView({ behavior: 'smooth' }), 300); - }; - - const userId = identityApi.getUserId(); - const profile = identityApi.getProfile(); - const displayName = profile.displayName ?? userId; - const SignInAvatar = () => ( - - {displayName[0]} - - ); - - return ( - <> - - - {open ? : } - - - ); -}; diff --git a/packages/core/src/layout/Sidebar/Settings/UserSettings.tsx b/packages/core/src/layout/Sidebar/Settings/UserSettings.tsx new file mode 100644 index 0000000000..8f541364ff --- /dev/null +++ b/packages/core/src/layout/Sidebar/Settings/UserSettings.tsx @@ -0,0 +1,78 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React, { useEffect, useContext } from 'react'; +import { Popover } from '@material-ui/core'; +import { SignInAvatar } from './SignInAvatar'; +import { SettingsDialog } from './SettingsDialog'; +import { SidebarItem } from '../Items'; +import { useUserProfile } from './useUserProfileInfo'; +import { SidebarContext } from '../config'; + +export const SidebarUserSettings = ({ + providerSettings, +}: { + providerSettings?: React.ReactNode; +}) => { + const { isOpen: sidebarOpen } = useContext(SidebarContext); + const { displayName } = useUserProfile(); + const [open, setOpen] = React.useState(false); + const [anchorEl, setAnchorEl] = React.useState( + undefined, + ); + + const handleOpen = (event?: React.MouseEvent) => { + setAnchorEl(event?.currentTarget ?? undefined); + setOpen(true); + }; + + const handleClose = () => { + setAnchorEl(undefined); + setOpen(false); + }; + + // Close the provider list when sidebar collapse + useEffect(() => { + if (!sidebarOpen && open) setOpen(false); + }, [open, sidebarOpen]); + + const SidebarAvatar = () => ; + + return ( + <> + + + + + + ); +}; diff --git a/packages/core/src/layout/Sidebar/Settings/UserSettingsMenu.tsx b/packages/core/src/layout/Sidebar/Settings/UserSettingsMenu.tsx new file mode 100644 index 0000000000..9ac287c57e --- /dev/null +++ b/packages/core/src/layout/Sidebar/Settings/UserSettingsMenu.tsx @@ -0,0 +1,55 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React from 'react'; +import { identityApiRef, useApi } from '@backstage/core-api'; +import { IconButton, ListItemIcon, Menu, MenuItem } from '@material-ui/core'; +import SignOutIcon from '@material-ui/icons/MeetingRoom'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; + +export const UserSettingsMenu = () => { + const identityApi = useApi(identityApiRef); + const [open, setOpen] = React.useState(false); + const [anchorEl, setAnchorEl] = React.useState( + undefined, + ); + + const handleOpen = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + setOpen(true); + }; + + const handleClose = () => { + setAnchorEl(undefined); + setOpen(false); + }; + + return ( + <> + + + + + identityApi.logout()}> + + + + Sign Out + + + + ); +}; diff --git a/packages/core/src/layout/Sidebar/Settings/index.ts b/packages/core/src/layout/Sidebar/Settings/index.ts index 6557ace53a..5479236a3b 100644 --- a/packages/core/src/layout/Sidebar/Settings/index.ts +++ b/packages/core/src/layout/Sidebar/Settings/index.ts @@ -17,4 +17,5 @@ export { ProviderSettingsItem } from './ProviderSettingsItem'; export { OAuthProviderSettings } from './OAuthProviderSettings'; export { OIDCProviderSettings } from './OIDCProviderSettings'; -export { UserProfile } from './UserProfile'; +// export { UserProfile } from './UserProfile'; +export { SidebarUserSettings } from './UserSettings'; diff --git a/packages/core/src/layout/Sidebar/Settings/useUserProfileInfo.ts b/packages/core/src/layout/Sidebar/Settings/useUserProfileInfo.ts new file mode 100644 index 0000000000..60dae294a5 --- /dev/null +++ b/packages/core/src/layout/Sidebar/Settings/useUserProfileInfo.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { useApi, identityApiRef } from '@backstage/core-api'; + +export const useUserProfile = () => { + const identityApi = useApi(identityApiRef); + const userId = identityApi.getUserId(); + const profile = identityApi.getProfile(); + const displayName = profile.displayName ?? userId; + + return { profile, displayName }; +}; diff --git a/packages/core/src/layout/Sidebar/SidebarThemeToggle.tsx b/packages/core/src/layout/Sidebar/SidebarThemeToggle.tsx deleted file mode 100644 index 32bc9d9632..0000000000 --- a/packages/core/src/layout/Sidebar/SidebarThemeToggle.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 React, { FC } from 'react'; -import { useObservable } from 'react-use'; -import LightIcon from '@material-ui/icons/WbSunny'; -import DarkIcon from '@material-ui/icons/Brightness2'; -import AutoIcon from '@material-ui/icons/BrightnessAuto'; -import { appThemeApiRef, useApi } from '@backstage/core-api'; -import { SidebarItem } from './Items'; - -export const SidebarThemeToggle: FC<{}> = () => { - const appThemeApi = useApi(appThemeApiRef); - const themeId = useObservable( - appThemeApi.activeThemeId$(), - appThemeApi.getActiveThemeId(), - ); - - let text = 'Auto'; - let icon = AutoIcon; - switch (themeId) { - case 'dark': - text = 'Dark mode'; - icon = DarkIcon; - break; - case 'light': - text = 'Light mode'; - icon = LightIcon; - break; - default: - break; - } - - const handleToggle = () => { - if (!themeId) { - appThemeApi.setActiveThemeId('light'); - } else if (themeId === 'light') { - appThemeApi.setActiveThemeId('dark'); - } else { - appThemeApi.setActiveThemeId(undefined); - } - }; - - return ; -}; diff --git a/packages/core/src/layout/Sidebar/UserSettings.tsx b/packages/core/src/layout/Sidebar/UserSettings.tsx deleted file mode 100644 index f586f6d077..0000000000 --- a/packages/core/src/layout/Sidebar/UserSettings.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { identityApiRef, useApi } from '@backstage/core-api'; -import Collapse from '@material-ui/core/Collapse'; -import SignOutIcon from '@material-ui/icons/MeetingRoom'; -import React, { useContext, useEffect } from 'react'; -import { SidebarContext } from './config'; -import { SidebarItem } from './Items'; -import { UserProfile as SidebarUserProfile } from './Settings'; - -type SidebarUserSettingsProps = { providerSettings?: React.ReactNode }; - -export function SidebarUserSettings({ - providerSettings, -}: SidebarUserSettingsProps) { - const { isOpen: sidebarOpen } = useContext(SidebarContext); - const [open, setOpen] = React.useState(false); - const identityApi = useApi(identityApiRef); - - // Close the provider list when sidebar collapse - useEffect(() => { - if (!sidebarOpen && open) setOpen(false); - }, [open, sidebarOpen]); - - return ( - <> - - - {providerSettings} - - identityApi.logout()} - /> - - - ); -} diff --git a/packages/core/src/layout/Sidebar/index.ts b/packages/core/src/layout/Sidebar/index.ts index fdca7e4eea..fb9a457dea 100644 --- a/packages/core/src/layout/Sidebar/index.ts +++ b/packages/core/src/layout/Sidebar/index.ts @@ -25,14 +25,15 @@ export { SidebarSpacer, } from './Items'; export { IntroCard, SidebarIntro } from './Intro'; -export { SidebarPinButton } from './PinButton'; +// export { SidebarPinButton } from './PinButton'; export { SIDEBAR_INTRO_LOCAL_STORAGE, SidebarContext, sidebarConfig, } from './config'; export type { SidebarContextType } from './config'; -export { SidebarThemeToggle } from './SidebarThemeToggle'; -export { SidebarUserSettings } from './UserSettings'; +// export { SidebarThemeToggle } from './SidebarThemeToggle'; +// export { SidebarUserSettings } from './UserSettings'; export { DefaultProviderSettings } from './DefaultProviderSettings'; export * from './Settings'; +// export { SidebarUserSettings } from './UserSettings';