/ packages / ui / src / components / molecules / ProfileEditor.tsx
ProfileEditor.tsx
  1  import { Button, Card, CardActions, CardContent, CardHeader } from '@mui/material';
  2  import Grid from '@mui/material/Grid2';
  3  import { Signal, useComputed, useSignal } from '@preact/signals-react';
  4  import { uuid } from 'ipmc-core';
  5  import { IConfigurationService, IConfigurationServiceSymbol, ILibrary, IProfile, isInternalProfile, isRemoteProfile } from 'ipmc-interfaces';
  6  import React from 'react';
  7  import { useService } from '../../context';
  8  import { useTranslation } from '../../hooks';
  9  import { FormList, SelectInput, TextInput } from '../atoms';
 10  import { LibraryEditor } from './LibraryEditor';
 11  
 12  export function ProfileEditor(props: { profile: IProfile, onCancel: () => void, onSave: () => void; }) {
 13  	const { profile, onCancel, onSave } = props;
 14  	const configService = useService<IConfigurationService>(IConfigurationServiceSymbol);
 15  	const _t = useTranslation();
 16  
 17  	const name = useSignal<string>(profile.name);
 18  	const type = useSignal<'internal' | 'remote'>(profile.type ?? 'internal');
 19  	const apiUrl = useSignal<string>(isRemoteProfile(profile) ? profile.url ?? '' : '');
 20  	const swarmKey = useSignal<string>(isInternalProfile(profile) ? profile.swarmKey ?? '' : '');
 21  	const port = useSignal<string>(isInternalProfile(profile) ? profile.port?.toString() ?? '' : '');
 22  	const bootstrap = useSignal<Signal<string>[]>(isInternalProfile(profile) ? profile.bootstrap?.map(i => new Signal(i)) ?? [] : []);
 23  	const libraries = useSignal<Signal<ILibrary>[]>(profile.libraries.map(i => new Signal(i)));
 24  
 25  	function save() {
 26  		configService.setProfile(profile.id, {
 27  			...(profile ?? {}),
 28  			name: name.value,
 29  			type: type.value,
 30  			...(type.value === 'internal' ? {
 31  				swarmKey: swarmKey.value === '' ? undefined : swarmKey.value,
 32  				port: port.value === '' ? undefined : parseInt(port.value),
 33  				bootstrap: bootstrap.value.map(s => s.value),
 34  			} : {
 35  				apiUrl: apiUrl.value === '' ? undefined : apiUrl.value,
 36  			}),
 37  			libraries: libraries.value.map(l => l.value),
 38  		});
 39  		onSave();
 40  	}
 41  
 42  	return (
 43  		<Card sx={{ maxHeight: '100%', overflow: 'auto' }}>
 44  			<CardHeader title={_t('EditProfile')} />
 45  			<CardContent>
 46  				<Grid container spacing={2}>
 47  					<Grid size={8}>
 48  						<TextInput
 49  							label={_t('Name')}
 50  							value={name}
 51  						/>
 52  					</Grid>
 53  					<Grid size={4}>
 54  						<SelectInput
 55  							value={type}
 56  							label={_t('ProfileType')}
 57  							options={{
 58  								'internal': _t('Internal'),
 59  								'remote': _t('Remote'),
 60  							}}
 61  						/>
 62  					</Grid>
 63  					{useComputed(() => type.value === 'internal' ? (<>
 64  						<Grid size={12}>
 65  							<TextInput
 66  								label={_t('SwarmKey')}
 67  								value={swarmKey}
 68  								key={'swarmKey'}
 69  								multiline={true}
 70  								rows={3}
 71  							/>
 72  						</Grid>
 73  						<Grid size={12}>
 74  							<TextInput
 75  								label={_t('Port')}
 76  								value={port}
 77  								key={'port'}
 78  							/>
 79  						</Grid>
 80  						<Grid size={12}>
 81  							<FormList
 82  								label={_t('Bootstrap')}
 83  								values={bootstrap}
 84  								renderControl={(item) => (
 85  									<TextInput
 86  										value={item}
 87  									/>
 88  								)}
 89  								createItem={() => ''}
 90  							/>
 91  						</Grid>
 92  					</>) : (<>
 93  						<Grid size={12}>
 94  							<TextInput
 95  								label={_t('ApiUrl')}
 96  								value={apiUrl}
 97  								key={'apiUrl'}
 98  							/>
 99  						</Grid>
100  					</>))}
101  					<Grid size={12}>
102  						<FormList
103  							label={_t('Libraries')}
104  							values={libraries}
105  							renderControl={(item) => (
106  								<LibraryEditor
107  									value={item}
108  								/>
109  							)}
110  							createItem={() => ({
111  								id: uuid(),
112  								upstream: '',
113  								name: '',
114  								type: 'movie',
115  							} as ILibrary)}
116  						/>
117  					</Grid>
118  				</Grid>
119  			</CardContent>
120  			<CardActions>
121  				<Button onClick={() => onCancel()}>{_t('Cancel')}</Button>
122  				<Button onClick={() => save()}>{_t('Save')}</Button>
123  			</CardActions>
124  		</Card>
125  	);
126  }