diff --git a/client/src/components/windows/settings/IntegrationSettingsEditor.tsx b/client/src/components/windows/settings/IntegrationSettingsEditor.tsx index 18df746..0210d58 100644 --- a/client/src/components/windows/settings/IntegrationSettingsEditor.tsx +++ b/client/src/components/windows/settings/IntegrationSettingsEditor.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useAuth } from '../../../lib/useAuth'; -import { Box, CircularProgress, IconButton, Typography, FormControl, Select, MenuItem, TextField, Menu, Button } from '@material-ui/core'; +import { Box, CircularProgress, IconButton, Typography, FormControl, Select, MenuItem, TextField, Menu, Button, Card, CardHeader, CardContent, CardActions } from '@material-ui/core'; import { getIntegrations, createIntegration, modifyIntegration, deleteIntegration } from '../../../lib/backend/integrations'; import AddIcon from '@material-ui/icons/Add'; import EditIcon from '@material-ui/icons/Edit'; @@ -31,93 +31,100 @@ function EditSpotifyClientCredentialsDetails(props: { onChangeClientSecret: (v: string) => void, }) { return - - Client id: - {props.editing ? - props.onChangeClientId(e.target.value)} - /> : - {props.clientId}} + + props.onChangeClientId(e.target.value)} + /> - - Client secret: - {props.editing ? - props.onChangeClientSecret(e.target.value)} - /> : - {props.clientSecret}} + + props.onChangeClientSecret(e.target.value)} + /> ; } function EditIntegration(props: EditIntegrationProps) { let IntegrationHeaders: Record = { - [serverApi.IntegrationType.SpotifyClientCredentials]: - - Spotify - + [serverApi.IntegrationType.SpotifyClientCredentials]: + + + Spotify + } - return - {IntegrationHeaders[props.integration.type]} - - Name: - {props.editing ? + return + + + + props.onChange({ ...props.integration, name: e.target.value, }, props.editing)} - /> : - {props.integration.name}} - - {props.integration.type === serverApi.IntegrationType.SpotifyClientCredentials && - props.onChange({ - ...props.integration, - details: { - ...props.integration.details, - clientId: v, - } - }, props.editing)} - onChangeClientSecret={(v: string) => props.onChange({ - ...props.integration, - details: { - ...props.integration.details, - clientSecret: v, - } - }, props.editing)} - /> - } - {!props.editing && !props.submitting && { props.onChange(props.integration, true); }} - >} - {props.editing && !props.submitting && { props.onSubmit(); }} - >} - {!props.submitting && { props.onDelete(); }} - >} - {!props.submitting && !props.editing && props.upstreamId !== null && } - {props.submitting && } - + /> + + {props.integration.type === serverApi.IntegrationType.SpotifyClientCredentials && + props.onChange({ + ...props.integration, + details: { + ...props.integration.details, + clientId: v, + } + }, props.editing)} + onChangeClientSecret={(v: string) => props.onChange({ + ...props.integration, + details: { + ...props.integration.details, + clientSecret: v, + } + }, props.editing)} + /> + } + + + {!props.editing && !props.submitting && { props.onChange(props.integration, true); }} + >} + {props.editing && !props.submitting && { props.onSubmit(); }} + >} + {!props.submitting && { props.onDelete(); }} + >} + {!props.submitting && !props.editing && props.upstreamId !== null && } + {props.submitting && } + + } function AddIntegrationMenu(props: { @@ -198,10 +205,11 @@ export default function IntegrationSettingsEditor(props: {}) { } const deleteEditor = (state: EditorState) => { - if (!state.upstreamId) { - throw new Error('Cannot delete integration: has no upstream') - } - deleteIntegration(state.upstreamId).then((response: any) => { + let promise: Promise = state.upstreamId ? + deleteIntegration(state.upstreamId) : + (async () => {})(); + + promise.then((response: any) => { let cpy = _.cloneDeep(editors).filter( (e: any) => e.id !== state.id ); @@ -225,62 +233,62 @@ export default function IntegrationSettingsEditor(props: {}) { }); }, []); - // FIXME: add button should show a drop-down to choose a fixed integration type. - // Otherwise we need dynamic switching of the type's fields. return <> {editors === null && } - {editors && <> - {editors.map((state: EditorState) => { - if (!editors) { - throw new Error('cannot change editors before loading integrations.') - } - let cpy: EditorState[] = _.cloneDeep(editors); - cpy.forEach((s: any) => { - if (s.id === state.id) { - s.integration = p; - s.editing = editing; + {editors && + {editors.map((state: EditorState) => + { + if (!editors) { + throw new Error('cannot change editors before loading integrations.') } - }) - setEditors(cpy); - }} - onSubmit={() => { - if (!editors) { - throw new Error('cannot submit editors before loading integrations.') - } - let cpy: EditorState[] = _.cloneDeep(editors); - cpy.forEach((s: any) => { - if (s.id === state.id) { - s.submitting = true; + let cpy: EditorState[] = _.cloneDeep(editors); + cpy.forEach((s: any) => { + if (s.id === state.id) { + s.integration = p; + s.editing = editing; + } + }) + setEditors(cpy); + }} + onSubmit={() => { + if (!editors) { + throw new Error('cannot submit editors before loading integrations.') } - }) - setEditors(cpy); - submitEditor(state); - }} - onDelete={() => { - if (!editors) { - throw new Error('cannot submit editors before loading integrations.') - } - let cpy: EditorState[] = _.cloneDeep(editors); - cpy.forEach((s: any) => { - if (s.id === state.id) { - s.submitting = true; + let cpy: EditorState[] = _.cloneDeep(editors); + cpy.forEach((s: any) => { + if (s.id === state.id) { + s.submitting = true; + } + }) + setEditors(cpy); + submitEditor(state); + }} + onDelete={() => { + if (!editors) { + throw new Error('cannot submit editors before loading integrations.') } - }) - setEditors(cpy); - deleteEditor(state); - }} - />)} + let cpy: EditorState[] = _.cloneDeep(editors); + cpy.forEach((s: any) => { + if (s.id === state.id) { + s.submitting = true; + } + }) + setEditors(cpy); + deleteEditor(state); + }} + /> + )} - } + } { return useContext(authContext); }; +function persistAuth(auth: AuthUser | null) { + let s = window.sessionStorage; + + if(auth === null) { + s.removeItem('userId'); + s.removeItem('userEmail'); + return; + } + + s.setItem('userId', auth.id.toString()); + s.setItem('userEmail', auth.email); + // TODO icon +} + +function loadAuth(): AuthUser | null { + let s = window.sessionStorage; + let id = s.getItem('userId'); + let email = s.getItem('userEmail'); + + if (id && email) { + return { + id: parseInt(id), + email: email, + icon: + } + } + return null; +} + function useProvideAuth() { - const [user, setUser] = useState(null); + const [user, setUser] = useState(loadAuth()); // TODO: password maybe shouldn't be encoded into the URL. const signin = (email: string, password: string) => { @@ -59,6 +88,7 @@ function useProvideAuth() { icon: , } setUser(user); + persistAuth(user); return user; })(); }; @@ -89,6 +119,7 @@ function useProvideAuth() { throw new Error("Failed to log out."); } setUser(null); + persistAuth(null); })(); };