Remove old Select, change Switch for Checkbox
This commit is contained in:
+1
-2
@@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.4.2",
|
"@headlessui/react": "^1.4.2",
|
||||||
"@meshtastic/meshtasticjs": "^0.6.24",
|
"@meshtastic/meshtasticjs": "^0.6.25",
|
||||||
"@reduxjs/toolkit": "^1.6.2",
|
"@reduxjs/toolkit": "^1.6.2",
|
||||||
"apexcharts": "^3.29.0",
|
"apexcharts": "^3.29.0",
|
||||||
"boring-avatars": "^1.5.8",
|
"boring-avatars": "^1.5.8",
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
"react-apexcharts": "^1.3.9",
|
"react-apexcharts": "^1.3.9",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-file-icon": "^1.1.0",
|
"react-file-icon": "^1.1.0",
|
||||||
"react-flags-select": "^2.1.2",
|
|
||||||
"react-hook-form": "^7.19.1",
|
"react-hook-form": "^7.19.1",
|
||||||
"react-i18next": "^11.13.0",
|
"react-i18next": "^11.13.0",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
|
|||||||
Generated
+4
-21
@@ -2,7 +2,7 @@ lockfileVersion: 5.3
|
|||||||
|
|
||||||
specifiers:
|
specifiers:
|
||||||
'@headlessui/react': ^1.4.2
|
'@headlessui/react': ^1.4.2
|
||||||
'@meshtastic/meshtasticjs': ^0.6.24
|
'@meshtastic/meshtasticjs': ^0.6.25
|
||||||
'@reduxjs/toolkit': ^1.6.2
|
'@reduxjs/toolkit': ^1.6.2
|
||||||
'@snowpack/plugin-dotenv': ^2.2.0
|
'@snowpack/plugin-dotenv': ^2.2.0
|
||||||
'@snowpack/plugin-postcss': ^1.4.3
|
'@snowpack/plugin-postcss': ^1.4.3
|
||||||
@@ -39,7 +39,6 @@ specifiers:
|
|||||||
react-apexcharts: ^1.3.9
|
react-apexcharts: ^1.3.9
|
||||||
react-dom: ^17.0.2
|
react-dom: ^17.0.2
|
||||||
react-file-icon: ^1.1.0
|
react-file-icon: ^1.1.0
|
||||||
react-flags-select: ^2.1.2
|
|
||||||
react-hook-form: ^7.19.1
|
react-hook-form: ^7.19.1
|
||||||
react-i18next: ^11.13.0
|
react-i18next: ^11.13.0
|
||||||
react-icons: ^4.3.1
|
react-icons: ^4.3.1
|
||||||
@@ -54,7 +53,7 @@ specifiers:
|
|||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@headlessui/react': 1.4.2_react-dom@17.0.2+react@17.0.2
|
'@headlessui/react': 1.4.2_react-dom@17.0.2+react@17.0.2
|
||||||
'@meshtastic/meshtasticjs': 0.6.24
|
'@meshtastic/meshtasticjs': 0.6.25
|
||||||
'@reduxjs/toolkit': 1.6.2_react-redux@7.2.6+react@17.0.2
|
'@reduxjs/toolkit': 1.6.2_react-redux@7.2.6+react@17.0.2
|
||||||
apexcharts: 3.29.0
|
apexcharts: 3.29.0
|
||||||
boring-avatars: 1.5.8
|
boring-avatars: 1.5.8
|
||||||
@@ -65,7 +64,6 @@ dependencies:
|
|||||||
react-apexcharts: 1.3.9_apexcharts@3.29.0+react@17.0.2
|
react-apexcharts: 1.3.9_apexcharts@3.29.0+react@17.0.2
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 17.0.2_react@17.0.2
|
||||||
react-file-icon: 1.1.0_react-dom@17.0.2+react@17.0.2
|
react-file-icon: 1.1.0_react-dom@17.0.2+react@17.0.2
|
||||||
react-flags-select: 2.1.2_react-dom@17.0.2+react@17.0.2
|
|
||||||
react-hook-form: 7.19.1_react@17.0.2
|
react-hook-form: 7.19.1_react@17.0.2
|
||||||
react-i18next: 11.13.0_i18next@21.4.1+react@17.0.2
|
react-i18next: 11.13.0_i18next@21.4.1+react@17.0.2
|
||||||
react-icons: 4.3.1_react@17.0.2
|
react-icons: 4.3.1_react@17.0.2
|
||||||
@@ -426,8 +424,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==}
|
resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@meshtastic/meshtasticjs/0.6.24:
|
/@meshtastic/meshtasticjs/0.6.25:
|
||||||
resolution: {integrity: sha512-zdIxyIL6a+UUgZdZvxeRhK/xVhLYB0ZeB5OuA9peRFVE/ICHmAhkmNb58G1hDr0Lq3mPtmlsnh0DiPkI5O4TnQ==}
|
resolution: {integrity: sha512-/FVmKIFpzSo2xguJ0+HfnpN9/6TS3ReMOXL29U7CsPnqGwePC3JJd3THNn2+ofOa//Iy7xGTYah0nF+LH1znJQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@protobuf-ts/runtime': 2.0.7
|
'@protobuf-ts/runtime': 2.0.7
|
||||||
node-fetch: 3.1.0
|
node-fetch: 3.1.0
|
||||||
@@ -1582,10 +1580,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==}
|
resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/classnames/2.3.1:
|
|
||||||
resolution: {integrity: sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/clean-stack/2.2.0:
|
/clean-stack/2.2.0:
|
||||||
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
|
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -4466,17 +4460,6 @@ packages:
|
|||||||
tinycolor2: 1.4.2
|
tinycolor2: 1.4.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/react-flags-select/2.1.2_react-dom@17.0.2+react@17.0.2:
|
|
||||||
resolution: {integrity: sha512-nx/6mY/nKVJB9sVZOylJoSI6idTYZfu0dtUQ0N1L+cD8VAPNl5c/lxL7yyi9vtn66hDRFy6Sr16GzsBj3aoZfQ==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=16.8.0'
|
|
||||||
react-dom: '>=16.8.0'
|
|
||||||
dependencies:
|
|
||||||
classnames: 2.3.1
|
|
||||||
react: 17.0.2
|
|
||||||
react-dom: 17.0.2_react@17.0.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/react-hook-form/7.19.1_react@17.0.2:
|
/react-hook-form/7.19.1_react@17.0.2:
|
||||||
resolution: {integrity: sha512-e0Oii07qNAa72JeGUT5czVCMwdAFPxmxYvd1Y9oPy2KVD6ZGblN6DG1G7AwL9Bz2lOPFZu15SRNnn0Vpx/eGdg==}
|
resolution: {integrity: sha512-e0Oii07qNAa72JeGUT5czVCMwdAFPxmxYvd1Y9oPy2KVD6ZGblN6DG1G7AwL9Bz2lOPFZu15SRNnn0Vpx/eGdg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//@ts-check
|
||||||
|
|
||||||
/** @type {import("snowpack").SnowpackUserConfig } */
|
/** @type {import("snowpack").SnowpackUserConfig } */
|
||||||
export default {
|
export default {
|
||||||
mount: {
|
mount: {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { FiEdit3, FiSave } from 'react-icons/fi';
|
|||||||
import { Protobuf } from '@meshtastic/meshtasticjs';
|
import { Protobuf } from '@meshtastic/meshtasticjs';
|
||||||
|
|
||||||
import { connection } from '../core/connection.js';
|
import { connection } from '../core/connection.js';
|
||||||
import { EnumSelect } from './generic/form/EnumSelect.jsx';
|
|
||||||
import { Input } from './generic/form/Input.jsx';
|
import { Input } from './generic/form/Input.jsx';
|
||||||
|
import { Select } from './generic/form/Select.jsx';
|
||||||
import { IconButton } from './generic/IconButton.jsx';
|
import { IconButton } from './generic/IconButton.jsx';
|
||||||
|
|
||||||
export interface ChannelProps {
|
export interface ChannelProps {
|
||||||
@@ -77,7 +77,7 @@ export const Channel = ({ channel }: ChannelProps): JSX.Element => {
|
|||||||
<div className="my-auto space-x-2">
|
<div className="my-auto space-x-2">
|
||||||
<form>
|
<form>
|
||||||
<div className="flex space-x-2">
|
<div className="flex space-x-2">
|
||||||
<EnumSelect
|
<Select
|
||||||
label="Channel Type"
|
label="Channel Type"
|
||||||
optionsEnum={Protobuf.Channel_Role}
|
optionsEnum={Protobuf.Channel_Role}
|
||||||
{...register('role', { valueAsNumber: true })}
|
{...register('role', { valueAsNumber: true })}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
|
|||||||
import { Input } from '@components/generic/form/Input';
|
import { Input } from '@components/generic/form/Input';
|
||||||
import { connection } from '@core/connection';
|
import { connection } from '@core/connection';
|
||||||
|
|
||||||
import { EnumSelect } from '../generic/form/EnumSelect.jsx';
|
import { Select } from '../generic/form/Select.jsx';
|
||||||
import { IconButton } from '../generic/IconButton.jsx';
|
import { IconButton } from '../generic/IconButton.jsx';
|
||||||
|
|
||||||
export const MessageBar = (): JSX.Element => {
|
export const MessageBar = (): JSX.Element => {
|
||||||
@@ -40,7 +40,7 @@ export const MessageBar = (): JSX.Element => {
|
|||||||
sendMessage();
|
sendMessage();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<EnumSelect
|
<Select
|
||||||
onChange={(e): void => {
|
onChange={(e): void => {
|
||||||
setDestinationNode(parseInt(e.target.value));
|
setDestinationNode(parseInt(e.target.value));
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { FiChevronDown } from 'react-icons/fi';
|
|
||||||
|
|
||||||
import { Listbox } from '@headlessui/react';
|
|
||||||
|
|
||||||
export interface SelectProps {
|
|
||||||
label: string;
|
|
||||||
options: {
|
|
||||||
name: string;
|
|
||||||
value: string;
|
|
||||||
icon: JSX.Element;
|
|
||||||
}[];
|
|
||||||
id: string;
|
|
||||||
active: {
|
|
||||||
name: string;
|
|
||||||
value: string;
|
|
||||||
icon: JSX.Element;
|
|
||||||
};
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Select = ({
|
|
||||||
label,
|
|
||||||
options,
|
|
||||||
id,
|
|
||||||
active,
|
|
||||||
onChange,
|
|
||||||
}: SelectProps): JSX.Element => {
|
|
||||||
return (
|
|
||||||
<div className="w-full">
|
|
||||||
<label
|
|
||||||
htmlFor={id}
|
|
||||||
className="block text-sm font-medium text-black dark:text-white"
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<Listbox value={active.value} onChange={onChange}>
|
|
||||||
<div className="relative mt-1">
|
|
||||||
<Listbox.Button className="flex w-full text-left bg-white border rounded-md shadow-sm h-11 focus:outline-none focus:border-primary dark:focus:border-primary dark:bg-secondaryDark dark:border-gray-600 dark:text-white">
|
|
||||||
<div className="mx-2 my-auto">{active.icon}</div>
|
|
||||||
<span className="block my-auto truncate">{active.name}</span>
|
|
||||||
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
|
||||||
<FiChevronDown
|
|
||||||
className="w-5 h-5 text-gray-400"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</Listbox.Button>
|
|
||||||
|
|
||||||
<Listbox.Options className="absolute w-full bg-white border rounded-md shadow-sm focus:outline-none dark:bg-secondaryDark dark:border-gray-600 dark:text-white">
|
|
||||||
{options.map((option) => (
|
|
||||||
<Listbox.Option
|
|
||||||
key={option.value}
|
|
||||||
className={({ active, selected }): string =>
|
|
||||||
`cursor-default select-none relative py-2 pr-4 first:rounded-t-md last:rounded-b-md dark:text-white ${
|
|
||||||
active || selected
|
|
||||||
? 'bg-gray-200 dark:bg-primaryDark'
|
|
||||||
: 'text-gray-900'
|
|
||||||
}`
|
|
||||||
}
|
|
||||||
value={option.value}
|
|
||||||
>
|
|
||||||
{({ selected }): JSX.Element => (
|
|
||||||
<>
|
|
||||||
<span
|
|
||||||
className={`flex truncate ${
|
|
||||||
selected ? 'font-medium' : 'font-normal'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className="mx-4 my-auto">{option.icon}</div>
|
|
||||||
{option.name}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Listbox.Option>
|
|
||||||
))}
|
|
||||||
</Listbox.Options>
|
|
||||||
</div>
|
|
||||||
</Listbox>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { Switch } from '@headlessui/react';
|
|
||||||
|
|
||||||
import { Label } from './form/Label.jsx';
|
|
||||||
|
|
||||||
type DefaultButtonProps = JSX.IntrinsicElements['button'];
|
|
||||||
|
|
||||||
interface ToggleProps extends DefaultButtonProps {
|
|
||||||
action?: (enabled: boolean) => void;
|
|
||||||
label: string;
|
|
||||||
valid?: boolean;
|
|
||||||
validationMessage?: string;
|
|
||||||
checked?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Toggle = ({
|
|
||||||
action,
|
|
||||||
label,
|
|
||||||
valid,
|
|
||||||
validationMessage,
|
|
||||||
checked,
|
|
||||||
id,
|
|
||||||
...props
|
|
||||||
}: ToggleProps): JSX.Element => {
|
|
||||||
const [enabled, setEnabled] = React.useState(false);
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (checked !== undefined) {
|
|
||||||
setEnabled(checked);
|
|
||||||
}
|
|
||||||
}, [checked]);
|
|
||||||
|
|
||||||
const handleToggle = (enabled: boolean) => {
|
|
||||||
setEnabled(enabled);
|
|
||||||
if (action) {
|
|
||||||
action(enabled);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col w-full">
|
|
||||||
<Label label={label} />
|
|
||||||
{/* <label
|
|
||||||
htmlFor={id}
|
|
||||||
className="block text-sm font-medium text-black dark:text-white"
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</label> */}
|
|
||||||
<div className="ml-auto">
|
|
||||||
<Switch
|
|
||||||
id={id}
|
|
||||||
{...props}
|
|
||||||
checked={enabled}
|
|
||||||
onChange={handleToggle}
|
|
||||||
className={`${
|
|
||||||
enabled ? 'bg-primary' : 'bg-gray-200 dark:bg-secondaryDark'
|
|
||||||
}
|
|
||||||
relative inline-flex flex-shrink-0 h-[38px] w-[74px] border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75`}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Use setting</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`${enabled ? 'translate-x-9' : 'translate-x-0'}
|
|
||||||
pointer-events-none inline-block h-[34px] w-[34px] rounded-full bg-white shadow-lg transform ring-0 transition ease-in-out duration-200`}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
</div>
|
|
||||||
{!valid && (
|
|
||||||
<div className="text-sm text-gray-600">{validationMessage}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Label } from './Label.jsx';
|
||||||
|
|
||||||
|
type DefaultInputProps = JSX.IntrinsicElements['input'];
|
||||||
|
|
||||||
|
interface CheckboxProps extends DefaultInputProps {
|
||||||
|
action?: (enabled: boolean) => void;
|
||||||
|
label: string;
|
||||||
|
valid?: boolean;
|
||||||
|
validationMessage?: string;
|
||||||
|
error?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Checkbox = ({
|
||||||
|
label,
|
||||||
|
valid,
|
||||||
|
validationMessage,
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
...props
|
||||||
|
}: CheckboxProps): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col w-full">
|
||||||
|
<Label label={label} />
|
||||||
|
<div className="ml-auto">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id={id}
|
||||||
|
className={`appearance-none w-8 h-8 border rounded-md focus:outline-none checked:bg-primary checked:border-transparent ${
|
||||||
|
props.disabled
|
||||||
|
? 'bg-gray-200 text-gray-500 dark:bg-gray-800 dark:text-gray-400 border-gray-400'
|
||||||
|
: ''
|
||||||
|
} ${
|
||||||
|
error
|
||||||
|
? 'border-red-500'
|
||||||
|
: props.disabled
|
||||||
|
? 'border-gray-200'
|
||||||
|
: ' focus-within:border-primary hover:border-primary'
|
||||||
|
}`}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{!valid && (
|
||||||
|
<div className="text-sm text-gray-600">{validationMessage}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -19,7 +19,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||||||
<InputWrapper error={error} disabled={props.disabled}>
|
<InputWrapper error={error} disabled={props.disabled}>
|
||||||
<input
|
<input
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className="w-full h-10 px-3 py-2 bg-transparent focus:outline-none focus:border-primary"
|
className="w-full h-10 px-3 py-2 bg-transparent focus:outline-none"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
{action && <div className="flex mr-1">{action}</div>}
|
{action && <div className="flex mr-1">{action}</div>}
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ export interface LabelProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const Label = ({ label, error }: LabelProps): JSX.Element => (
|
export const Label = ({ label, error }: LabelProps): JSX.Element => (
|
||||||
<label className="text-xs font-semibold text-gray-500">
|
<label className="flex py-1 text-xs font-semibold text-gray-500">
|
||||||
{label}
|
{label}
|
||||||
{error && <span className="ml-2 text-red-500">{error}</span>}
|
{error && <span className="ml-2 text-red-500">{error}</span>}
|
||||||
|
<div className="flex-grow h-0.5 my-auto ml-2 dark:bg-gray-600 bg-gray-500" />
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface SelectProps extends DefaultSelectProps {
|
|||||||
small?: boolean;
|
small?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EnumSelect = React.forwardRef<HTMLSelectElement, SelectProps>(
|
export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
||||||
({ options, optionsEnum, label, error, small, ...props }, ref) => {
|
({ options, optionsEnum, label, error, small, ...props }, ref) => {
|
||||||
const optionsEnumValues = optionsEnum
|
const optionsEnumValues = optionsEnum
|
||||||
? Object.entries(optionsEnum).filter(
|
? Object.entries(optionsEnum).filter(
|
||||||
@@ -29,7 +29,7 @@ export const EnumSelect = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|||||||
<InputWrapper>
|
<InputWrapper>
|
||||||
<select
|
<select
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={`w-full bg-transparent focus:outline-none focus:border-primary ${
|
className={`w-full bg-white dark:bg-transparent focus:outline-none focus:border-primary ${
|
||||||
small ? 'py-1 mx-1' : 'h-10 mx-2'
|
small ? 'py-1 mx-1' : 'h-10 mx-2'
|
||||||
}`}
|
}`}
|
||||||
disabled={
|
disabled={
|
||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { FiHash } from 'react-icons/fi';
|
import { FiHash } from 'react-icons/fi';
|
||||||
|
|
||||||
import { EnumSelect } from '@app/components/generic/form/EnumSelect.jsx';
|
import { Select } from '@app/components/generic/form/Select.jsx';
|
||||||
import { Message } from '@components/chat/Message';
|
import { Message } from '@components/chat/Message';
|
||||||
import { MessageBar } from '@components/chat/MessageBar';
|
import { MessageBar } from '@components/chat/MessageBar';
|
||||||
import { Protobuf } from '@meshtastic/meshtasticjs';
|
import { Protobuf } from '@meshtastic/meshtasticjs';
|
||||||
@@ -19,7 +19,7 @@ export const Messages = (): JSX.Element => {
|
|||||||
<div className="flex justify-between w-full px-2 border-b dark:border-gray-600 dark:text-gray-300">
|
<div className="flex justify-between w-full px-2 border-b dark:border-gray-600 dark:text-gray-300">
|
||||||
<div className="flex py-2 my-auto text-sm">
|
<div className="flex py-2 my-auto text-sm">
|
||||||
<FiHash className="w-4 h-4 my-auto mr-1" />
|
<FiHash className="w-4 h-4 my-auto mr-1" />
|
||||||
<EnumSelect
|
<Select
|
||||||
options={channels
|
options={channels
|
||||||
.filter(
|
.filter(
|
||||||
(channel) =>
|
(channel) =>
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { FiMenu, FiTerminal } from 'react-icons/fi';
|
|||||||
|
|
||||||
import { Card } from '@app/components/generic/Card';
|
import { Card } from '@app/components/generic/Card';
|
||||||
import { Chart } from '@app/components/generic/Chart';
|
import { Chart } from '@app/components/generic/Chart';
|
||||||
|
import { Checkbox } from '@app/components/generic/form/Checkbox';
|
||||||
import { Input } from '@app/components/generic/form/Input';
|
import { Input } from '@app/components/generic/form/Input';
|
||||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||||
import { Toggle } from '@app/components/generic/Toggle';
|
|
||||||
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||||
import type { Protobuf } from '@meshtastic/meshtasticjs';
|
import type { Protobuf } from '@meshtastic/meshtasticjs';
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ export const Node = ({ navOpen, setNavOpen, node }: NodeProps): JSX.Element => {
|
|||||||
<form className="space-y-4">
|
<form className="space-y-4">
|
||||||
<Input label={'Device Name'} />
|
<Input label={'Device Name'} />
|
||||||
<Input label={'Short Name'} maxLength={3} />
|
<Input label={'Short Name'} maxLength={3} />
|
||||||
<Toggle label="Licenced Operator?" />
|
<Checkbox label="Licenced Operator?" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { FiMenu, FiSave } from 'react-icons/fi';
|
import { FiMenu, FiSave } from 'react-icons/fi';
|
||||||
|
|
||||||
import { Card } from '@app/components/generic/Card';
|
import { Card } from '@app/components/generic/Card';
|
||||||
|
import { Checkbox } from '@app/components/generic/form/Checkbox';
|
||||||
import { Input } from '@app/components/generic/form/Input.jsx';
|
import { Input } from '@app/components/generic/form/Input.jsx';
|
||||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||||
import { Toggle } from '@app/components/generic/Toggle';
|
|
||||||
import { connection } from '@app/core/connection.js';
|
import { connection } from '@app/core/connection.js';
|
||||||
import { useAppSelector } from '@app/hooks/redux';
|
import { useAppSelector } from '@app/hooks/redux';
|
||||||
import { Button } from '@components/generic/Button';
|
import { Button } from '@components/generic/Button';
|
||||||
@@ -70,31 +70,13 @@ export const RangeTest = ({
|
|||||||
<Card title="Range Test" description="Settings">
|
<Card title="Range Test" description="Settings">
|
||||||
<div className="w-full max-w-3xl p-10 md:max-w-xl">
|
<div className="w-full max-w-3xl p-10 md:max-w-xl">
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<Toggle
|
<Checkbox
|
||||||
label="Range Test Plugin Enabled?"
|
label="Range Test Plugin Enabled?"
|
||||||
checked={preferences.rangeTestPluginEnabled}
|
{...register('rangeTestPluginEnabled')}
|
||||||
action={(checked): void => {
|
|
||||||
void connection.setPreferences({
|
|
||||||
...preferences,
|
|
||||||
rangeTestPluginEnabled: checked,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Toggle
|
<Checkbox
|
||||||
label="Range Test Plugin Save?"
|
label="Range Test Plugin Save?"
|
||||||
checked={preferences.rangeTestPluginEnabled}
|
{...register('rangeTestPluginSave')}
|
||||||
action={(checked): void => {
|
|
||||||
void connection.setPreferences({
|
|
||||||
...preferences,
|
|
||||||
rangeTestPluginSave: checked,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Toggle
|
|
||||||
label="Range Test Plugin Save?"
|
|
||||||
{...register('rangeTestPluginEnabled', {
|
|
||||||
valueAsNumber: true,
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FiMenu, FiSave } from 'react-icons/fi';
|
|||||||
import { Channel } from '@app/components/Channel.jsx';
|
import { Channel } from '@app/components/Channel.jsx';
|
||||||
import { Card } from '@app/components/generic/Card';
|
import { Card } from '@app/components/generic/Card';
|
||||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||||
|
import { connection } from '@app/core/connection.js';
|
||||||
import { useAppSelector } from '@app/hooks/redux.js';
|
import { useAppSelector } from '@app/hooks/redux.js';
|
||||||
import { Button } from '@components/generic/Button';
|
import { Button } from '@components/generic/Button';
|
||||||
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||||
@@ -67,7 +68,12 @@ export const Channels = ({
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
<div className="flex space-x-52">
|
<div className="flex space-x-52">
|
||||||
<div className="text-sm font-thin text-gray-400 dark:text-gray-300">
|
<div
|
||||||
|
onClick={(): Promise<void> => {
|
||||||
|
return connection.confirmSetChannel();
|
||||||
|
}}
|
||||||
|
className="text-sm font-thin text-gray-400 dark:text-gray-300"
|
||||||
|
>
|
||||||
Please ensure any changes are working before confirming
|
Please ensure any changes are working before confirming
|
||||||
</div>
|
</div>
|
||||||
<Button active>Confirm</Button>
|
<Button active>Confirm</Button>
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { FiCheck, FiMenu, FiSave } from 'react-icons/fi';
|
import { FiCheck, FiMenu, FiSave } from 'react-icons/fi';
|
||||||
|
|
||||||
import { Card } from '@app/components/generic/Card';
|
import { Card } from '@app/components/generic/Card';
|
||||||
import { EnumSelect } from '@app/components/generic/form/EnumSelect';
|
import { Checkbox } from '@app/components/generic/form/Checkbox';
|
||||||
import { Input } from '@app/components/generic/form/Input';
|
import { Input } from '@app/components/generic/form/Input';
|
||||||
|
import { Select } from '@app/components/generic/form/Select';
|
||||||
import { IconButton } from '@app/components/generic/IconButton';
|
import { IconButton } from '@app/components/generic/IconButton';
|
||||||
import { Toggle } from '@app/components/generic/Toggle';
|
|
||||||
import { connection, setConnection } from '@app/core/connection';
|
import { connection, setConnection } from '@app/core/connection';
|
||||||
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
|
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
|
||||||
import { Button } from '@components/generic/Button';
|
import { Button } from '@components/generic/Button';
|
||||||
@@ -147,7 +147,7 @@ export const Connection = ({
|
|||||||
>
|
>
|
||||||
<div className="w-full max-w-3xl p-10 md:max-w-xl">
|
<div className="w-full max-w-3xl p-10 md:max-w-xl">
|
||||||
<form className="space-y-2" onSubmit={onSubmit}>
|
<form className="space-y-2" onSubmit={onSubmit}>
|
||||||
<EnumSelect
|
<Select
|
||||||
label="Method"
|
label="Method"
|
||||||
optionsEnum={connType}
|
optionsEnum={connType}
|
||||||
value={selectedConnType}
|
value={selectedConnType}
|
||||||
@@ -157,7 +157,7 @@ export const Connection = ({
|
|||||||
/>
|
/>
|
||||||
{selectedConnType === connType.HTTP && (
|
{selectedConnType === connType.HTTP && (
|
||||||
<>
|
<>
|
||||||
<EnumSelect
|
<Select
|
||||||
label="Host Source"
|
label="Host Source"
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
@@ -179,7 +179,7 @@ export const Connection = ({
|
|||||||
) : (
|
) : (
|
||||||
<Input label="Host" />
|
<Input label="Host" />
|
||||||
)}
|
)}
|
||||||
<Toggle label="Use TLS?" />
|
<Checkbox label="Use TLS?" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{selectedConnType === connType.BLE && (
|
{selectedConnType === connType.BLE && (
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { FiMenu, FiSave } from 'react-icons/fi';
|
import { FiMenu, FiSave } from 'react-icons/fi';
|
||||||
|
|
||||||
import { Card } from '@app/components/generic/Card';
|
import { Card } from '@app/components/generic/Card';
|
||||||
|
import { Checkbox } from '@app/components/generic/form/Checkbox';
|
||||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||||
import { Toggle } from '@app/components/generic/Toggle';
|
|
||||||
import { connection } from '@app/core/connection';
|
import { connection } from '@app/core/connection';
|
||||||
import { useAppSelector } from '@app/hooks/redux';
|
import { useAppSelector } from '@app/hooks/redux';
|
||||||
import { Button } from '@components/generic/Button';
|
import { Button } from '@components/generic/Button';
|
||||||
@@ -81,7 +81,7 @@ export const Device = ({ navOpen, setNavOpen }: DeviceProps): JSX.Element => {
|
|||||||
maxLength={3}
|
maxLength={3}
|
||||||
{...register('shortName')}
|
{...register('shortName')}
|
||||||
/>
|
/>
|
||||||
<Toggle label="Licenced Operator?" {...register('isLicensed')} />
|
<Checkbox label="Licenced Operator?" {...register('isLicensed')} />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Jp, Pt, Us } from 'react-flags-select';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { FiMenu, FiSave } from 'react-icons/fi';
|
import { FiMenu, FiSave } from 'react-icons/fi';
|
||||||
|
|
||||||
import { Card } from '@app/components/generic/Card';
|
import { Card } from '@app/components/generic/Card';
|
||||||
import { Select } from '@app/components/generic/Select';
|
import { Select } from '@app/components/generic/form/Select';
|
||||||
import i18n from '@app/core/translation';
|
import i18n from '@app/core/translation';
|
||||||
import { Button } from '@components/generic/Button';
|
import { Button } from '@components/generic/Button';
|
||||||
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||||
@@ -52,40 +51,23 @@ export const Interface = ({
|
|||||||
<div className="w-full max-w-3xl p-10 space-y-2 md:max-w-xl">
|
<div className="w-full max-w-3xl p-10 space-y-2 md:max-w-xl">
|
||||||
<Select
|
<Select
|
||||||
label="Language"
|
label="Language"
|
||||||
active={
|
|
||||||
i18n.language === 'en'
|
|
||||||
? {
|
|
||||||
name: 'English',
|
|
||||||
value: 'en',
|
|
||||||
icon: <Us />,
|
|
||||||
}
|
|
||||||
: i18n.language === 'pt'
|
|
||||||
? { name: 'Português', value: 'pt', icon: <Pt /> }
|
|
||||||
: i18n.language === 'jp'
|
|
||||||
? { name: '日本', value: 'jp', icon: <Jp /> }
|
|
||||||
: { name: 'English', value: 'en', icon: <Us /> }
|
|
||||||
}
|
|
||||||
onChange={(value): void => {
|
|
||||||
void i18n.changeLanguage(value);
|
|
||||||
}}
|
|
||||||
id="aaa"
|
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
name: 'English',
|
name: 'English',
|
||||||
value: 'en',
|
value: 'en',
|
||||||
icon: <Us className="w-6" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Português',
|
|
||||||
value: 'pt',
|
|
||||||
icon: <Pt className="w-6" />,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '日本',
|
name: '日本',
|
||||||
value: 'jp',
|
value: 'jp',
|
||||||
icon: <Jp className="w-6" />,
|
},
|
||||||
|
{
|
||||||
|
name: 'Português',
|
||||||
|
value: 'pt',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
onChange={(e): void => {
|
||||||
|
void i18n.changeLanguage(e.target.value);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { FiMenu, FiSave, FiXCircle } from 'react-icons/fi';
|
import { FiMenu, FiSave, FiXCircle } from 'react-icons/fi';
|
||||||
|
|
||||||
import { Card } from '@app/components/generic/Card';
|
import { Card } from '@app/components/generic/Card';
|
||||||
import { EnumSelect } from '@app/components/generic/form/EnumSelect.jsx';
|
import { Checkbox } from '@app/components/generic/form/Checkbox';
|
||||||
|
import { Select } from '@app/components/generic/form/Select.jsx';
|
||||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||||
import { Toggle } from '@app/components/generic/Toggle.jsx';
|
|
||||||
import { connection } from '@app/core/connection';
|
import { connection } from '@app/core/connection';
|
||||||
import { useAppSelector } from '@app/hooks/redux';
|
import { useAppSelector } from '@app/hooks/redux';
|
||||||
import { Button } from '@components/generic/Button';
|
import { Button } from '@components/generic/Button';
|
||||||
@@ -89,18 +89,21 @@ export const Radio = ({ navOpen, setNavOpen }: RadioProps): JSX.Element => {
|
|||||||
label={'Broadcast Interval (seconds)'}
|
label={'Broadcast Interval (seconds)'}
|
||||||
{...register('positionBroadcastSecs', { valueAsNumber: true })}
|
{...register('positionBroadcastSecs', { valueAsNumber: true })}
|
||||||
/>
|
/>
|
||||||
<EnumSelect
|
<Select
|
||||||
label="Position Type"
|
label="Position Type"
|
||||||
optionsEnum={Protobuf.PositionFlags}
|
optionsEnum={Protobuf.PositionFlags}
|
||||||
{...register('positionFlags', { valueAsNumber: true })}
|
{...register('positionFlags', { valueAsNumber: true })}
|
||||||
/>
|
/>
|
||||||
<Toggle label="Use Fixed Position" {...register('fixedPosition')} />
|
<Checkbox
|
||||||
<EnumSelect
|
label="Use Fixed Position"
|
||||||
|
{...register('fixedPosition')}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
label="Location Sharing"
|
label="Location Sharing"
|
||||||
optionsEnum={Protobuf.LocationSharing}
|
optionsEnum={Protobuf.LocationSharing}
|
||||||
{...register('locationShare', { valueAsNumber: true })}
|
{...register('locationShare', { valueAsNumber: true })}
|
||||||
/>
|
/>
|
||||||
<EnumSelect
|
<Select
|
||||||
label="GPS Mode"
|
label="GPS Mode"
|
||||||
optionsEnum={Protobuf.GpsOperation}
|
optionsEnum={Protobuf.GpsOperation}
|
||||||
{...register('gpsOperation', { valueAsNumber: true })}
|
{...register('gpsOperation', { valueAsNumber: true })}
|
||||||
|
|||||||
Reference in New Issue
Block a user