Implementing an 'account' dialog (WIP)
This commit is contained in:
parent
0e2ffb0cf2
commit
a36c8a28a4
|
@ -0,0 +1,7 @@
|
||||||
|
.control {
|
||||||
|
opacity: 1;
|
||||||
|
position: fixed !important;
|
||||||
|
top: 0px;
|
||||||
|
margin-left: calc(100% - 35px) !important;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
import { Component, createSignal, For } from 'solid-js';
|
||||||
|
|
||||||
|
import PersonIcon from '@suid/icons-material/Person';
|
||||||
|
|
||||||
|
import style from './Account.module.css';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
IconButton,
|
||||||
|
InputLabel,
|
||||||
|
NativeSelect,
|
||||||
|
TextField,
|
||||||
|
} from '@suid/material';
|
||||||
|
import { useI18n } from '@solid-primitives/i18n';
|
||||||
|
import Dialog from '../dialog';
|
||||||
|
import dispatch from '../../workers/dispatcher-main';
|
||||||
|
import allGpxes from '../all-gpxes';
|
||||||
|
import gpx from '../gpx';
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
|
const Account: Component<{}> = (props) => {
|
||||||
|
const [t] = useI18n();
|
||||||
|
const [open, setOpen] = createSignal(false);
|
||||||
|
const [settings, setSettings] = createSignal<any>();
|
||||||
|
const [accounts, setAccounts] = createSignal<any>();
|
||||||
|
const [account, setAccount] = createSignal<any>({});
|
||||||
|
|
||||||
|
const handleClickOpen = async () => {
|
||||||
|
setOpen(true);
|
||||||
|
const newSettings: any = await dispatch({
|
||||||
|
action: 'getSettings',
|
||||||
|
});
|
||||||
|
setSettings(newSettings || {});
|
||||||
|
const newAccounts: any = await dispatch({
|
||||||
|
action: 'getAccounts',
|
||||||
|
});
|
||||||
|
setAccounts([
|
||||||
|
{ id: '--new--', name: t('newAccount') },
|
||||||
|
...newAccounts.rows,
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
caller: 'Account / handleClickOpen',
|
||||||
|
settings: settings(),
|
||||||
|
accounts: accounts(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = (event: any, reason?: string) => {
|
||||||
|
console.log({
|
||||||
|
caller: 'Account / handleClose',
|
||||||
|
event,
|
||||||
|
reason,
|
||||||
|
});
|
||||||
|
if (reason === undefined) {
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeAccountHandler = (event: any) => {
|
||||||
|
const selectedAccountName = event.target.value;
|
||||||
|
const targetAccount =
|
||||||
|
accounts().filter((acc: any) => acc.name === selectedAccountName)[0] ||
|
||||||
|
{};
|
||||||
|
setAccount(cloneDeep(targetAccount));
|
||||||
|
console.log({
|
||||||
|
caller: 'Account / changeAccountHandler',
|
||||||
|
event,
|
||||||
|
selectedAccountName,
|
||||||
|
account: account(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeHandlerFactory = (path: string) => (event: any) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
const newAccount = cloneDeep(account());
|
||||||
|
newAccount[path] = value;
|
||||||
|
setAccount(newAccount);
|
||||||
|
console.log({
|
||||||
|
caller: 'Account / changeHandlerFactory / ' + path,
|
||||||
|
event,
|
||||||
|
value,
|
||||||
|
account: account(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div class={style.control}>
|
||||||
|
<IconButton onClick={handleClickOpen}>
|
||||||
|
<PersonIcon />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
<Dialog
|
||||||
|
open={open()}
|
||||||
|
title={t('account')}
|
||||||
|
closeHandler={handleClose}
|
||||||
|
fullScreen={true}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
component='form'
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
'& .MuiTextField-root': { m: 1, width: '100%' },
|
||||||
|
paddingTop: '5px',
|
||||||
|
}}
|
||||||
|
noValidate
|
||||||
|
autoComplete='off'
|
||||||
|
>
|
||||||
|
<InputLabel variant='normal' htmlFor='account-chooser'>
|
||||||
|
{t('accountChooser')}
|
||||||
|
</InputLabel>
|
||||||
|
<NativeSelect
|
||||||
|
inputProps={{
|
||||||
|
name: 'account-chooser',
|
||||||
|
id: 'account-chooser',
|
||||||
|
}}
|
||||||
|
onChange={changeAccountHandler}
|
||||||
|
>
|
||||||
|
<For each={accounts()}>
|
||||||
|
{(account: any) => (
|
||||||
|
<option value={account.id} selected={account.id === ''}>
|
||||||
|
{account.name}
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</NativeSelect>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label={t('accountName')}
|
||||||
|
value={account().name || ''}
|
||||||
|
onChange={changeHandlerFactory('name')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label={t('localDb')}
|
||||||
|
value={account().localDb || ''}
|
||||||
|
onChange={changeHandlerFactory('localDb')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label={t('remoteDbServer')}
|
||||||
|
value={account().remoteDbServer || ''}
|
||||||
|
onChange={changeHandlerFactory('remoteDbServer')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label={t('remoteDbUser')}
|
||||||
|
value={account().remoteDbUser || ''}
|
||||||
|
onChange={changeHandlerFactory('remoteDbUser')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label={t('remoteDbPassword')}
|
||||||
|
value={account().remoteDbPassword || ''}
|
||||||
|
onChange={changeHandlerFactory('remoteDbPassword')}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Account;
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from './Account';
|
|
@ -27,28 +27,14 @@ const Dialog: Component<{
|
||||||
backgroundColor: 'rgba(14, 116, 144, 0.7)',
|
backgroundColor: 'rgba(14, 116, 144, 0.7)',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
clear: 'both',
|
clear: 'both',
|
||||||
paddingRight: '20px',
|
margin: '0',
|
||||||
}}
|
paddingLeft: '0',
|
||||||
>
|
|
||||||
<Grid container spacing={2} alignItems='center'>
|
|
||||||
<Grid item xs={11}>
|
|
||||||
{props.title}
|
|
||||||
</Grid>
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={1}
|
|
||||||
sx={{
|
|
||||||
alignSelf: 'right',
|
|
||||||
marginRight: '0px',
|
|
||||||
paddingRight: '0px',
|
|
||||||
paddingTop: '16px',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton onClick={props.closeHandler}>
|
<IconButton onClick={props.closeHandler}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Grid>
|
{props.title}
|
||||||
</Grid>
|
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent sx={{ width: 'calc(100% - 60px)' }}>
|
<DialogContent sx={{ width: 'calc(100% - 60px)' }}>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import dispatch from '../../workers/dispatcher-main';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
import { AndroidFullScreen } from '@awesome-cordova-plugins/android-full-screen';
|
import { AndroidFullScreen } from '@awesome-cordova-plugins/android-full-screen';
|
||||||
|
import Account from '../account';
|
||||||
|
|
||||||
const [getState, setState] = createSignal({
|
const [getState, setState] = createSignal({
|
||||||
lon: 0,
|
lon: 0,
|
||||||
|
@ -271,6 +272,7 @@ const Map: Component = () => {
|
||||||
<GpxImport />
|
<GpxImport />
|
||||||
<MapTileProvider />
|
<MapTileProvider />
|
||||||
<GpxDialog />
|
<GpxDialog />
|
||||||
|
<Account />
|
||||||
<AllGpxes map={getMap} />
|
<AllGpxes map={getMap} />
|
||||||
<Infos />
|
<Infos />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { getFamily, put } from './lib';
|
||||||
|
import getUri from '../lib/ids';
|
||||||
|
|
||||||
|
export const getAccounts = async () => {
|
||||||
|
return await getFamily('account', {}, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const putAccount = async (name: string, account: any) => {
|
||||||
|
const uri = getUri('account', name);
|
||||||
|
return await put(uri, 'account', (_: any) => account, {}, true);
|
||||||
|
};
|
|
@ -36,8 +36,9 @@ export const put = async (
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFamily = async (key: string, options: any = {}) => {
|
export const getFamily = async (key: string, options: any = {}, local: boolean = false) => {
|
||||||
return await db.allDocs({
|
const targetDb = local ? localDb : db;
|
||||||
|
return await targetDb.allDocs({
|
||||||
startkey: key,
|
startkey: key,
|
||||||
endkey: key + '\ufff0',
|
endkey: key + '\ufff0',
|
||||||
...options,
|
...options,
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { get, put } from './lib';
|
||||||
|
|
||||||
|
export const getSettings = async () => {
|
||||||
|
try {
|
||||||
|
return await get('settings', true);
|
||||||
|
} catch (err) {
|
||||||
|
console.error({ caller: 'getSettings', err });
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const putSettings = async (settings: any) => {
|
||||||
|
return await put('settings', 'settings', (_: any) => settings, {}, true);
|
||||||
|
};
|
|
@ -52,6 +52,15 @@ const dict = {
|
||||||
gpxPauseRecording: 'Suspend recording',
|
gpxPauseRecording: 'Suspend recording',
|
||||||
ResumeRecording: 'Resume recording',
|
ResumeRecording: 'Resume recording',
|
||||||
StopRecording: 'Stop recording',
|
StopRecording: 'Stop recording',
|
||||||
|
|
||||||
|
account: 'User account',
|
||||||
|
newAccount: '-- new account --',
|
||||||
|
accountChooser: 'Choose an account',
|
||||||
|
accountName: 'Account name',
|
||||||
|
localDb: 'Local database name',
|
||||||
|
remoteDbServer: 'Remote database server URL',
|
||||||
|
remoteDbUser: 'Remote database user',
|
||||||
|
remoteDbPassword: 'Remote database password',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default dict;
|
export default dict;
|
||||||
|
|
|
@ -57,6 +57,15 @@ const dict = {
|
||||||
gpxPauseRecording: "Mettre l'enregistrement en pause",
|
gpxPauseRecording: "Mettre l'enregistrement en pause",
|
||||||
gpxResumeRecording: "Reprendre l'enregistrement",
|
gpxResumeRecording: "Reprendre l'enregistrement",
|
||||||
gpxStopRecording: "Arrêter l'enregistrement",
|
gpxStopRecording: "Arrêter l'enregistrement",
|
||||||
|
|
||||||
|
account: 'Compte utilisateur',
|
||||||
|
newAccount: '-- nouveau compte --',
|
||||||
|
accountChooser: 'Choisissez un compte',
|
||||||
|
accountName: 'Nom du compte',
|
||||||
|
localDb: 'Nom de la base de données locale',
|
||||||
|
remoteDbServer: 'Adresse du serveur de base de données distant',
|
||||||
|
remoteDbUser: 'Utilisateur de la base de données distante',
|
||||||
|
remoteDbPassword: 'Mot de passe de la base de données distante',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default dict;
|
export default dict;
|
||||||
|
|
|
@ -26,6 +26,8 @@ const coding = {
|
||||||
|
|
||||||
const routes = {
|
const routes = {
|
||||||
dbdef: route('dbdef', coding),
|
dbdef: route('dbdef', coding),
|
||||||
|
state: route('state', coding),
|
||||||
|
account: route('account/:account', coding),
|
||||||
settings: route('settings', coding),
|
settings: route('settings', coding),
|
||||||
gpx: route('gpx/:gpx', coding),
|
gpx: route('gpx/:gpx', coding),
|
||||||
wpt: route('gpx/:gpx/1wpt/:wpt', coding),
|
wpt: route('gpx/:gpx/1wpt/:wpt', coding),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/// <reference lib="webworker" />
|
/// <reference lib="webworker" />
|
||||||
import { initDb } from '../db';
|
import { initDb } from '../db';
|
||||||
|
import { getAccounts, putAccount } from '../db/account';
|
||||||
import { cancelWatch, getAndWatch } from '../db/change-handler';
|
import { cancelWatch, getAndWatch } from '../db/change-handler';
|
||||||
import {
|
import {
|
||||||
putNewGpx,
|
putNewGpx,
|
||||||
|
@ -11,6 +12,7 @@ import {
|
||||||
getAllGpxes,
|
getAllGpxes,
|
||||||
getAllGpxesWithSummary,
|
getAllGpxesWithSummary,
|
||||||
} from '../db/gpx';
|
} from '../db/gpx';
|
||||||
|
import { getSettings, putSettings } from '../db/settings';
|
||||||
import { getState, setState } from '../db/state';
|
import { getState, setState } from '../db/state';
|
||||||
import { getTrk, putNewTrk } from '../db/trk';
|
import { getTrk, putNewTrk } from '../db/trk';
|
||||||
import { getTrkseg, appendTrkpt } from '../db/trkseg';
|
import { getTrkseg, appendTrkpt } from '../db/trkseg';
|
||||||
|
@ -43,6 +45,12 @@ onmessage = async function (e) {
|
||||||
|
|
||||||
getAndWatch,
|
getAndWatch,
|
||||||
cancelWatch,
|
cancelWatch,
|
||||||
|
|
||||||
|
getSettings,
|
||||||
|
putSettings,
|
||||||
|
|
||||||
|
getAccounts,
|
||||||
|
putAccount,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log({ caller: 'dispatcher-worker / onmessage', e });
|
console.log({ caller: 'dispatcher-worker / onmessage', e });
|
||||||
|
|
Loading…
Reference in New Issue