+ );
}
-export default translate(styled(General)`
- .settings--cutomToggle {
- text-align: right;
- }
-
- .ui.menu {
- justify-content: flex-end;
- margin-bottom: 0;
-
- .active.item {
- font-weight: bold;
- }
- }
-
- .sub-label {
- cursor: pointer;
- padding: 0rem .5833rem;
- text-align: right;
- }
-`);
+export default translate(General);
diff --git a/packages/app-settings/src/SelectUrl.tsx b/packages/app-settings/src/SelectUrl.tsx
new file mode 100644
index 0000000000..1dc92970ad
--- /dev/null
+++ b/packages/app-settings/src/SelectUrl.tsx
@@ -0,0 +1,123 @@
+// Copyright 2017-2019 @polkadot/app-settings authors & contributors
+// This software may be modified and distributed under the terms
+// of the Apache-2.0 license. See the LICENSE file for details.
+
+import { I18nProps } from '@polkadot/react-components/types';
+import { Option } from './types';
+
+import React, { useEffect, useState } from 'react';
+import styled from 'styled-components';
+import { Dropdown, Input, Toggle } from '@polkadot/react-components';
+import uiSettings from '@polkadot/ui-settings';
+
+import translate from './translate';
+import { createOption } from './util';
+
+interface Props extends I18nProps {
+ className?: string;
+ onChange: (url: string) => void;
+}
+
+interface StateUrl {
+ isValid: boolean;
+ url: string;
+}
+
+interface State extends StateUrl {
+ isCustom: boolean;
+}
+
+const endpointOptions = uiSettings.availableNodes.map((o): Option => createOption(o, ['local']));
+
+// check the validity of the url
+function isValidUrl (url: string): boolean {
+ return (
+ // some random length... we probably want to parse via some lib
+ (url.length >= 7) &&
+ // check that it starts with a valid ws identifier
+ (url.startsWith('ws://') || url.startsWith('wss://'))
+ );
+}
+
+// sanitize a url and check it for validity
+function makeUrl (_url: string): StateUrl {
+ const url = _url.trim();
+ const isValid = isValidUrl(url);
+
+ return { isValid, url };
+}
+
+// this allows us to retrieve the initial state by reading the settings and the applying
+// validation on-top of the values retrieved
+function getInitialState (): State {
+ const url = uiSettings.get().apiUrl;
+ const isCustom = uiSettings.availableNodes.reduce((isCustom: boolean, { value }): boolean => {
+ return isCustom && value !== url;
+ }, true);
+ const isValid = isValidUrl(url);
+
+ return { isCustom, isValid, url };
+}
+
+function SelectUrl ({ className, onChange, t }: Props): React.ReactElement {
+ const [info, setInfo] = useState(getInitialState());
+ const { isCustom, isValid, url } = info;
+ const help = t('Select the remote endpoint, either from the dropdown on manual entered via the custom toggle');
+ const label = t('remote node/endpoint to connect to');
+ const _onChangeUrl = (url: string): void => setInfo({ ...info, ...makeUrl(url) });
+ const _onChangeCustom = (isCustom: boolean): void =>
+ setInfo({
+ ...makeUrl(
+ isCustom
+ ? info.url
+ : uiSettings.availableNodes[0].value as string
+ ),
+ isCustom
+ });
+
+ useEffect((): void => {
+ if (onChange && info.isValid) {
+ onChange(info.url);
+ }
+ }, [info]);
+
+ return (
+
+
{
+ isCustom
+ ?
+ :
+ }
+
+
+ );
+}
+
+export default translate(
+ styled(SelectUrl)`
+ position: relative;
+
+ .settings--customToggle {
+ position: absolute;
+ top: .5rem;
+ right: 3.5rem;
+ }
+ `
+);
diff --git a/packages/app-settings/src/types.ts b/packages/app-settings/src/types.ts
new file mode 100644
index 0000000000..897cf11ffb
--- /dev/null
+++ b/packages/app-settings/src/types.ts
@@ -0,0 +1,14 @@
+// Copyright 2017-2019 @polkadot/app-settings authors & contributors
+// This software may be modified and distributed under the terms
+// of the Apache-2.0 license. See the LICENSE file for details.
+
+export interface Option {
+ text: React.ReactNode;
+ value: string | number;
+}
+
+export interface SetOption {
+ info: string;
+ text: string;
+ value: string | number;
+}
diff --git a/packages/app-settings/src/util.tsx b/packages/app-settings/src/util.tsx
new file mode 100644
index 0000000000..2ac7ee0789
--- /dev/null
+++ b/packages/app-settings/src/util.tsx
@@ -0,0 +1,41 @@
+// Copyright 2017-2019 @polkadot/app-settings authors & contributors
+// This software may be modified and distributed under the terms
+// of the Apache-2.0 license. See the LICENSE file for details.
+
+import { SettingsStruct } from '@polkadot/ui-settings/types';
+import { Option, SetOption } from './types';
+
+import React from 'react';
+import { ChainImg } from '@polkadot/react-components';
+import uiSettings from '@polkadot/ui-settings';
+
+export function createOption ({ info, text, value }: SetOption, overrides: string[] = [], override: string = 'empty'): Option {
+ return {
+ text: (
+
+
+
{text}
+
+ ),
+ value
+ };
+}
+
+export function saveAndReload (settings: SettingsStruct | null): void {
+ if (!settings) {
+ return;
+ }
+
+ uiSettings.set(settings);
+
+ // HACK This is terribe, but since the API needs to re-connect, but since
+ // the API does not yet handle re-connections properly, it is what it is
+ window.location.reload();
+}
diff --git a/packages/react-components/src/Dropdown.tsx b/packages/react-components/src/Dropdown.tsx
index 87b61fac63..7a47b20cfb 100644
--- a/packages/react-components/src/Dropdown.tsx
+++ b/packages/react-components/src/Dropdown.tsx
@@ -172,7 +172,7 @@ export default styled(Dropdown)`
> .text > .ui--Dropdown-item {
.ui--Dropdown-icon {
left: -2.6rem;
- top: -1rem;
+ top: -1.15rem;
opacity: 1;
}
diff --git a/packages/react-components/src/Toggle.tsx b/packages/react-components/src/Toggle.tsx
index 813a4a32f4..6022cd4d09 100644
--- a/packages/react-components/src/Toggle.tsx
+++ b/packages/react-components/src/Toggle.tsx
@@ -23,6 +23,7 @@ class Toggle extends React.PureComponent {
return (