Revert "making databag pretty, thanks @lil5"

This reverts commit afb7632edf.
This commit is contained in:
Roland Osborne 2024-05-02 15:16:20 -07:00
parent d38d60119b
commit 55e054abb5
231 changed files with 4313 additions and 6447 deletions

View File

@ -1,39 +1,21 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link
rel="icon"
href="/favicon.ico"
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta
name="theme-color"
content="#000000"
/>
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="theme-color" content="#000000" />
<meta
name="Databag"
content="Communication for the Decentralized Web"
/>
<link
rel="apple-touch-icon"
href="/logo192.png"
/>
<link
rel="manifest"
href="/manifest.json"
/>
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>Databag</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script
type="module"
src="/src/index.tsx"
></script>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>

View File

@ -1 +1,2 @@
module.exports = '';
module.exports = '';

View File

@ -1,6 +1,7 @@
import 'antd/dist/reset.css';
import { Colors } from 'constants/Colors';
import { HashRouter as Router, Routes, Route } from 'react-router-dom';
import { HashRouter as Router, Routes, Route } from "react-router-dom";
import { AppContextProvider } from 'context/AppContext';
import { AccountContextProvider } from 'context/AccountContext';
@ -22,6 +23,7 @@ import { Dashboard } from './dashboard/Dashboard';
import { ConfigProvider } from 'antd';
function App() {
return (
<UploadContextProvider>
<ChannelContextProvider>
@ -33,46 +35,25 @@ function App() {
<SettingsContextProvider>
<AppContextProvider>
<AppWrapper>
<ConfigProvider
theme={{
token: {
colorPrimary: Colors.primary,
colorLink: Colors.primary,
colorLinkHover: Colors.background,
colorBgBase: Colors.cancel,
},
}}
>
<ConfigProvider theme={{ token: {
colorPrimary: Colors.primary,
colorLink: Colors.primary,
colorLinkHover: Colors.background,
colorBgBase: Colors.cancel,
} }}>
<Router>
<Routes>
<Route
path="/"
element={<Root />}
/>
<Route
path="/dashboard"
element={<Dashboard />}
/>
<Route
path="/admin"
element={<Access mode="admin" />}
/>
<Route
path="/login"
element={<Access mode="login" />}
/>
<Route
path="/create"
element={<Access mode="create" />}
/>
<Route
path="/session"
element={
<ConversationContextProvider>
<Session />
</ConversationContextProvider>
}
></Route>
<Route path="/" element={ <Root /> } />
<Route path="/dashboard" element={ <Dashboard /> } />
<Route path="/admin" element={ <Access mode="admin" /> } />
<Route path="/login" element={ <Access mode="login" /> } />
<Route path="/create" element={ <Access mode="create" /> } />
<Route path="/session" element={
<ConversationContextProvider>
<Session />
</ConversationContextProvider>
}>
</Route>
</Routes>
</Router>
</ConfigProvider>

View File

@ -2,7 +2,7 @@ import styled from 'styled-components';
export const AccessWrapper = styled.div`
height: 100%;
color: ${(props) => props.theme.hintText};
color: ${props => props.theme.hintText};
.footer {
display: flex;
@ -22,12 +22,12 @@ export const AccessWrapper = styled.div`
width: 100%;
height: 100%;
padding: 8px;
.center {
width: 100%;
height: 100%;
border-radius: 4px;
background: ${(props) => props.theme.frameArea};
background: ${props => props.theme.frameArea};
display: flex;
flex-direction: column;
align-items: center;
@ -44,7 +44,7 @@ export const AccessWrapper = styled.div`
width: 50%;
height: 100%;
padding: 32px;
background-color: ${(props) => props.theme.splashArea};
background-color: ${props => props.theme.splashArea};
.splash {
width: 100%;
@ -56,7 +56,7 @@ export const AccessWrapper = styled.div`
.right {
width: 50%;
height: 100%;
background: ${(props) => props.theme.frameArea};
background: ${props => props.theme.frameArea};
display: flex;
flex-direction: column;
align-items: center;

View File

@ -3,98 +3,104 @@ import { AccessWrapper } from './Access.styled';
import { Login } from './login/Login';
import { Admin } from './admin/Admin';
import { CreateAccount } from './createAccount/CreateAccount';
import { ThemeProvider } from 'styled-components';
import { ThemeProvider } from "styled-components";
import { Select } from 'antd';
import dogin from 'images/dogin.png';
import bogin from 'images/bogin.png';
export function Access({ mode }) {
const { state, actions } = useAccess();
return (
<ThemeProvider theme={state.colors}>
<AccessWrapper>
{(state.display === 'large' || state.display === 'xlarge') && (
{ (state.display === 'large' || state.display === 'xlarge') && (
<div className="split-layout">
<div className="left">
{state.scheme === 'dark' && (
<img
className="splash"
src={dogin}
alt="Databag Splash"
/>
{ state.scheme === 'dark' && (
<img className="splash" src={dogin} alt="Databag Splash" />
)}
{state.scheme === 'light' && (
<img
className="splash"
src={bogin}
alt="Databag Splash"
/>
{ state.scheme === 'light' && (
<img className="splash" src={bogin} alt="Databag Splash" />
)}
</div>
<div className="right">
{mode === 'login' && <Login />}
{mode === 'create' && <CreateAccount />}
{mode === 'admin' && <Admin />}
{ mode === 'login' && (
<Login />
)}
{ mode === 'create' && (
<CreateAccount />
)}
{ mode === 'admin' && (
<Admin />
)}
<div className="footer">
<div className="option">
<div className="label">{state.strings.theme}</div>
<Select
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.theme}
onChange={actions.setTheme}
options={[{ value: null, label: state.strings.default }, ...state.themes]}
/>
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.theme}
onChange={actions.setTheme}
options={[{value: null, label: state.strings.default}, ...state.themes]}
/>
</div>
<div className="option">
<div className="label">{state.strings.language}</div>
<Select
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.language}
onChange={actions.setLanguage}
options={[{ value: null, label: state.strings.default }, ...state.languages]}
/>
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.language}
onChange={actions.setLanguage}
options={[{value: null, label: state.strings.default}, ...state.languages]}
/>
</div>
</div>
</div>
</div>
)}
{(state.display === 'medium' || state.display === 'small') && (
{ (state.display === 'medium' || state.display === 'small') && (
<div className="full-layout">
<div className="center">
{mode === 'login' && <Login />}
{mode === 'create' && <CreateAccount />}
{mode === 'admin' && <Admin />}
{ mode === 'login' && (
<Login />
)}
{ mode === 'create' && (
<CreateAccount />
)}
{ mode === 'admin' && (
<Admin />
)}
<div className="footer">
<div className="option">
<div className="label">{state.strings.theme}</div>
<Select
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.theme}
onChange={actions.setTheme}
options={[{ value: null, label: state.strings.default }, ...state.themes]}
/>
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.theme}
onChange={actions.setTheme}
options={[{value: null, label: state.strings.default}, ...state.themes]}
/>
</div>
<div className="option">
<div className="label">{state.strings.language}</div>
<Select
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.language}
onChange={actions.setLanguage}
options={[{ value: null, label: state.strings.default }, ...state.languages]}
/>
defaultValue={null}
size="small"
style={{ width: 128 }}
value={state.language}
onChange={actions.setLanguage}
options={[{value: null, label: state.strings.default}, ...state.languages]}
/>
</div>
</div>
</div>
</div>
)}
@ -102,3 +108,4 @@ export function Access({ mode }) {
</ThemeProvider>
);
}

View File

@ -7,20 +7,20 @@ export const AdminWrapper = styled.div`
height: 90%;
display: flex;
flex-direction: column;
.disabled {
background-color: ${(props) => props.theme.disabledArea};
background-color: ${props => props.theme.disabledArea};
button {
color: ${(props) => props.theme.idleText};
color: ${props => props.theme.idleText};
}
}
.enabled {
background-color: ${(props) => props.theme.enabledArea};
background-color: ${props => props.theme.enabledArea};
button {
color: ${(props) => props.theme.activeText};
color: ${props => props.theme.activeText};
}
}
@ -54,7 +54,7 @@ export const AdminWrapper = styled.div`
.form-form {
flex: 2;
.form-button {
display: flex;
align-items: center;
@ -70,3 +70,5 @@ export const AdminWrapper = styled.div`
background-color: #444444;
}
`;

View File

@ -3,75 +3,59 @@ import { UserOutlined, LockOutlined } from '@ant-design/icons';
import { AdminWrapper } from './Admin.styled';
import { useAdmin } from './useAdmin.hook';
export function Admin() {
const [modal, modalContext] = Modal.useModal();
export function Admin() {
const [ modal, modalContext ] = Modal.useModal();
const { state, actions } = useAdmin();
const login = async () => {
try {
await actions.login();
} catch (err) {
}
catch(err) {
modal.error({
title: <span style={state.menuStyle}>{state.strings.adminError}</span>,
content: <span style={state.menuStyle}>{state.strings.adminMessage}</span>,
bodyStyle: { borderRadius: 8, padding: 16, ...state.menuStyle },
});
}
};
}
const keyDown = (e) => {
if (e.key === 'Enter') {
login();
login()
}
};
}
return (
<AdminWrapper>
{modalContext}
{ modalContext }
<div className="app-title">
<span>Databag</span>
<div
className="settings"
onClick={() => actions.navUser()}
>
<div className="settings" onClick={() => actions.navUser()}>
<UserOutlined />
</div>
</div>
<div className="form-title">{state.strings.admin}</div>
<div className="form-form">
<Form
name="basic"
wrapperCol={{ span: 24 }}
>
<Form name="basic" wrapperCol={{ span: 24, }}>
<Form.Item name="password">
<Input.Password
placeholder={state.unclaimed ? state.strings.newPassword : state.strings.password}
spellCheck="false"
onChange={(e) => actions.setPassword(e.target.value)}
autoComplete="current-password"
onKeyDown={(e) => keyDown(e)}
prefix={<LockOutlined />}
size="large"
/>
<Input.Password placeholder={ state.unclaimed ? state.strings.newPassword : state.strings.password } spellCheck="false"
onChange={(e) => actions.setPassword(e.target.value)} autoComplete="current-password"
onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
</Form.Item>
<div className="form-button">
<div className="form-login">
<Button
className={state.password ? 'enabled' : 'disabled'}
type="primary"
block
onClick={login}
size="middle"
loading={state.busy}
disabled={!state.password}
>
{state.strings.login}
</Button>
<Button className={state.password ? 'enabled' : 'disabled'} type="primary" block onClick={login} size="middle" loading={state.busy}
disabled={!state.password}>{state.strings.login}</Button>
</div>
</div>
</Form>
</div>
</AdminWrapper>
);
}
};

View File

@ -1,5 +1,5 @@
import { useContext, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useNavigate } from "react-router-dom";
import { getNodeStatus } from 'api/getNodeStatus';
import { setNodeStatus } from 'api/setNodeStatus';
import { getNodeConfig } from 'api/getNodeConfig';
@ -7,6 +7,7 @@ import { AppContext } from 'context/AppContext';
import { SettingsContext } from 'context/SettingsContext';
export function useAdmin() {
const [state, setState] = useState({
password: '',
placeholder: '',
@ -22,15 +23,16 @@ export function useAdmin() {
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
};
}
useEffect(() => {
const check = async () => {
try {
const unclaimed = await getNodeStatus();
updateState({ unclaimed });
} catch (err) {
console.log('getNodeStatus failed');
}
catch(err) {
console.log("getNodeStatus failed");
}
};
check();
@ -52,15 +54,16 @@ export function useAdmin() {
}
await getNodeConfig(state.password);
updateState({ busy: false });
app.actions.setAdmin(state.password);
} catch (err) {
app.actions.setAdmin(state.password);
}
catch(err) {
console.log(err);
updateState({ busy: false });
throw new Error('login failed');
throw new Error("login failed");
}
}
},
};
}
useEffect(() => {
const { strings, menuStyle } = settings.state;
@ -69,3 +72,4 @@ export function useAdmin() {
return { state, actions };
}

View File

@ -9,18 +9,18 @@ export const CreateAccountWrapper = styled.div`
flex-direction: column;
.disabled {
background-color: ${(props) => props.theme.disabledArea};
background-color: ${props => props.theme.disabledArea};
button {
color: ${(props) => props.theme.idleText};
color: ${props => props.theme.idleText};
}
}
.enabled {
background-color: ${(props) => props.theme.enabledArea};
background-color: ${props => props.theme.enabledArea};
button {
color: ${(props) => props.theme.activeText};
color: ${props => props.theme.activeText};
}
}
@ -58,7 +58,7 @@ export const CreateAccountWrapper = styled.div`
.form-space {
height: 8px;
}
.form-button {
display: flex;
align-items: center;
@ -78,3 +78,5 @@ export const CreateAccountWrapper = styled.div`
background-color: #444444;
}
`;

View File

@ -3,100 +3,64 @@ import { SettingOutlined, LockOutlined, UserOutlined } from '@ant-design/icons';
import { CreateAccountWrapper } from './CreateAccount.styled';
import { useCreateAccount } from './useCreateAccount.hook';
export function CreateAccount() {
const [modal, modalContext] = Modal.useModal();
export function CreateAccount() {
const [ modal, modalContext ] = Modal.useModal();
const { state, actions } = useCreateAccount();
const create = async () => {
try {
await actions.onCreateAccount();
} catch (err) {
}
catch(err) {
modal.error({
title: <span style={state.menuStyle}>{state.strings.createError}</span>,
content: <span style={state.menuStyle}>{state.strings.createMessage}</span>,
bodyStyle: { borderRadius: 8, padding: 16, ...state.menuStyle },
});
}
};
}
const keyDown = (e) => {
if (e.key === 'Enter') {
create();
create()
}
};
}
return (
<CreateAccountWrapper>
{modalContext}
{ modalContext }
<div className="app-title">
<span>Databag</span>
<div
className="settings"
onClick={() => actions.onSettings()}
>
<div className="settings" onClick={() => actions.onSettings()}>
<SettingOutlined />
</div>
</div>
<div className="form-title">{state.strings.createAccount}</div>
<div className="form-form">
<Form
name="basic"
wrapperCol={{ span: 24 }}
>
<Form.Item
name="username"
validateStatus={state.validateStatus}
help={state.help}
>
<Input
placeholder={state.strings.username}
spellCheck="false"
onChange={(e) => actions.setUsername(e.target.value)}
autoComplete="username"
autoCapitalize="none"
onKeyDown={(e) => keyDown(e)}
prefix={<UserOutlined />}
size="large"
/>
<Form name="basic" wrapperCol={{ span: 24, }}>
<Form.Item name="username" validateStatus={state.validateStatus} help={state.help}>
<Input placeholder={state.strings.username} spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
autoComplete="username" autoCapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
</Form.Item>
<div className="form-space"></div>
<Form.Item name="password">
<Input.Password
placeholder={state.strings.newPassword}
spellCheck="false"
onChange={(e) => actions.setPassword(e.target.value)}
autoComplete="new-password"
onKeyDown={(e) => keyDown(e)}
prefix={<LockOutlined />}
size="large"
/>
<Input.Password placeholder={state.strings.newPassword} spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
autoComplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
</Form.Item>
<Form.Item name="confirm">
<Input.Password
placeholder={state.strings.confirmPassword}
spellCheck="false"
onChange={(e) => actions.setConfirm(e.target.value)}
autoComplete="new-password"
onKeyDown={(e) => keyDown(e)}
prefix={<LockOutlined />}
size="large"
/>
<Input.Password placeholder={state.strings.confirmPassword} spellCheck="false" onChange={(e) => actions.setConfirm(e.target.value)}
autoComplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
</Form.Item>
<div className="form-button">
<div className="form-create">
<Button
className={actions.isDisabled() ? 'disabled' : 'enabled'}
type="primary"
block
onClick={create}
disabled={actions.isDisabled()}
loading={state.busy}
size="middle"
>
<Button className={actions.isDisabled() ? 'disabled' : 'enabled'} type="primary" block onClick={create} disabled={ actions.isDisabled()}
loading={state.busy} size="middle">
{state.strings.create}
</Button>
</div>
@ -104,17 +68,15 @@ export function CreateAccount() {
<div className="form-button">
<div className="form-login">
<Button
type="link"
block
onClick={(e) => actions.onLogin()}
>
<Button type="link" block onClick={(e) => actions.onLogin()}>
{state.strings.accountLogin}
</Button>
</div>
</div>
</Form>
</div>
</CreateAccountWrapper>
);
}
};

View File

@ -1,10 +1,11 @@
import { useContext, useState, useEffect, useRef } from 'react';
import { AppContext } from 'context/AppContext';
import { SettingsContext } from 'context/SettingsContext';
import { useNavigate, useLocation } from 'react-router-dom';
import { useNavigate, useLocation } from "react-router-dom";
import { getUsername } from 'api/getUsername';
export function useCreateAccount() {
const [checked, setChecked] = useState(true);
const [state, setState] = useState({
username: '',
@ -13,7 +14,7 @@ export function useCreateAccount() {
busy: false,
validatetatus: 'success',
help: '',
strings: {} as Record<string, string>,
strings: {} as Record<string,string>,
menuStyle: {},
});
@ -25,30 +26,33 @@ export function useCreateAccount() {
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
};
}
const usernameSet = (name) => {
setChecked(false);
clearTimeout(debounce.current);
setChecked(false)
clearTimeout(debounce.current)
debounce.current = setTimeout(async () => {
if (name !== '') {
try {
let valid = await getUsername(name, state.token);
let valid = await getUsername(name, state.token)
if (!valid) {
updateState({ validateStatus: 'error', help: 'Username is not available' });
} else {
updateState({ validateStatus: 'success', help: '' });
updateState({ validateStatus: 'error', help: 'Username is not available' })
}
setChecked(true);
} catch (err) {
else {
updateState({ validateStatus: 'success', help: '' })
}
setChecked(true)
}
catch(err) {
console.log(err);
}
} else {
}
else {
updateState({ validateStatus: 'success', help: '' });
setChecked(true);
}
}, 500);
};
}, 500)
}
const actions = {
setUsername: (username) => {
@ -63,32 +67,27 @@ export function useCreateAccount() {
},
isDisabled: () => {
const restricted = new RegExp('[!@#$%^&*() ,.?":{}|<>]', 'i');
if (
state.username === '' ||
restricted.test(state.username) ||
state.password === '' ||
state.password !== state.confirm ||
!checked ||
state.validateStatus === 'error'
) {
return true;
if (state.username === '' || restricted.test(state.username) || state.password === '' ||
state.password !== state.confirm || !checked || state.validateStatus === 'error') {
return true
}
return false;
return false
},
onSettings: () => {
navigate('/admin');
},
onCreateAccount: async () => {
if (!state.busy && state.username !== '' && state.password !== '' && state.password === state.confirm) {
updateState({ busy: true });
updateState({ busy: true })
try {
await app.actions.create(state.username, state.password, state.token);
} catch (err) {
await app.actions.create(state.username, state.password, state.token)
}
catch (err) {
console.log(err);
updateState({ busy: false });
updateState({ busy: false })
throw new Error('create failed: check with your admin');
}
updateState({ busy: false });
updateState({ busy: false })
}
},
onLogin: () => {
@ -103,11 +102,12 @@ export function useCreateAccount() {
useEffect(() => {
let params = new URLSearchParams(search);
let token = params.get('add');
let token = params.get("add");
if (token) {
updateState({ token });
}
}, [app, navigate, search]);
}, [app, navigate, search])
return { state, actions };
}

View File

@ -8,18 +8,18 @@ export const LoginWrapper = styled.div`
flex-direction: column;
.disabled {
background-color: ${(props) => props.theme.disabledArea};
background-color: ${props => props.theme.disabledArea};
button {
color: ${(props) => props.theme.idleText};
color: ${props => props.theme.idleText};
}
}
.enabled {
background-color: ${(props) => props.theme.enabledArea};
background-color: ${props => props.theme.enabledArea};
button {
color: ${(props) => props.theme.activeText};
color: ${props => props.theme.activeText};
}
}
@ -29,10 +29,10 @@ export const LoginWrapper = styled.div`
align-items: flex-start;
justify-content: center;
flex: 1;
color: ${(props) => props.theme.hintText};
color: ${props => props.theme.hintText};
.settings {
color: ${(props) => props.theme.hintText};
color: ${props => props.theme.hintText};
position: absolute;
top: 0px;
right: 0px;
@ -63,7 +63,7 @@ export const LoginWrapper = styled.div`
.form-form {
flex: 2;
.form-button {
display: flex;
align-items: center;
@ -79,3 +79,5 @@ export const LoginWrapper = styled.div`
background-color: #444444;
}
`;

View File

@ -3,103 +3,77 @@ import { SettingOutlined, LockOutlined, UserOutlined } from '@ant-design/icons';
import { LoginWrapper } from './Login.styled';
import { useLogin } from './useLogin.hook';
export function Login() {
const [modal, modalContext] = Modal.useModal();
export function Login() {
const [ modal, modalContext ] = Modal.useModal();
const { state, actions } = useLogin();
const login = async () => {
try {
await actions.onLogin();
} catch (err) {
}
catch(err) {
modal.error({
title: <span style={state.menuStyle}>{state.strings.loginError}</span>,
content: <span style={state.menuStyle}>{state.strings.loginMessage}</span>,
bodyStyle: { borderRadius: 8, padding: 16, ...state.menuStyle },
});
}
};
}
const keyDown = (e) => {
if (e.key === 'Enter') {
login();
login()
}
};
}
return (
<LoginWrapper>
{modalContext}
{ modalContext }
<div className="app-title">
<span>Databag</span>
<div
className="settings"
onClick={() => actions.onSettings()}
>
<div className="settings" onClick={() => actions.onSettings()}>
<SettingOutlined />
</div>
</div>
<div className="form-title">
<div>{state.strings.login}</div>
{!state.available && state.availableSet && <div className="form-message">{state.strings.toCreate}</div>}
<div>{ state.strings.login }</div>
{ !state.available && state.availableSet && (
<div className="form-message">{ state.strings.toCreate }</div>
)}
</div>
<div className="form-form">
<Form
name="basic"
wrapperCol={{ span: 24 }}
>
<Form name="basic" wrapperCol={{ span: 24, }}>
<Form.Item name="username">
<Input
placeholder={state.strings.username}
spellCheck="false"
onChange={(e) => actions.setUsername(e.target.value)}
autoComplete="username"
autoCapitalize="none"
onKeyDown={(e) => keyDown(e)}
prefix={<UserOutlined />}
size="large"
/>
<Input placeholder={state.strings.username} spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
autoComplete="username" autoCapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
</Form.Item>
<Form.Item name="password">
<Input.Password
placeholder={state.strings.password}
spellCheck="false"
onChange={(e) => actions.setPassword(e.target.value)}
autoComplete="current-password"
onKeyDown={(e) => keyDown(e)}
prefix={<LockOutlined />}
size="large"
/>
<Input.Password placeholder={state.strings.password} spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
autoComplete="current-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
</Form.Item>
<div className="form-button">
<div className="form-login">
<Button
className={actions.isDisabled() ? 'disabled' : 'enabled'}
type="primary"
block
onClick={login}
disabled={actions.isDisabled()}
size="middle"
loading={state.busy}
>
<Button className={actions.isDisabled() ? 'disabled' : 'enabled'} type="primary" block onClick={login} disabled={ actions.isDisabled()}
size="middle" loading={state.busy}>
{state.strings.login}
</Button>
</div>
</div>
<div className="form-button">
<Button
type="link"
block
disabled={!state.available}
onClick={(e) => actions.onCreate()}
>
<Button type="link" block disabled={ !state.available } onClick={(e) => actions.onCreate()}>
{state.strings.createAccount}
</Button>
</div>
</Form>
</div>
</LoginWrapper>
);
}
};

View File

@ -2,9 +2,10 @@ import { useContext, useState, useEffect } from 'react';
import { AppContext } from 'context/AppContext';
import { SettingsContext } from 'context/SettingsContext';
import { getAvailable } from 'api/getAvailable';
import { useLocation, useNavigate } from 'react-router-dom';
import { useLocation, useNavigate } from "react-router-dom";
export function useLogin() {
const [state, setState] = useState({
username: '',
password: '',
@ -12,7 +13,7 @@ export function useLogin() {
availableSet: false,
disabled: true,
busy: false,
strings: {} as Record<string, string>,
strings: {} as Record<string,string>,
menuStyle: {},
});
@ -23,7 +24,7 @@ export function useLogin() {
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
};
}
const actions = {
setUsername: (username) => {
@ -34,24 +35,25 @@ export function useLogin() {
},
isDisabled: () => {
if (state.username === '' || state.password === '') {
return true;
return true
}
return false;
return false
},
onSettings: () => {
navigate('/admin');
},
onLogin: async () => {
if (!state.busy && state.username !== '' && state.password !== '') {
updateState({ busy: true });
updateState({ busy: true })
try {
await app.actions.login(state.username, state.password);
} catch (err) {
await app.actions.login(state.username, state.password)
}
catch (err) {
console.log(err);
updateState({ busy: false });
updateState({ busy: false })
throw new Error('login failed: check your username and password');
}
updateState({ busy: false });
updateState({ busy: false })
}
},
onCreate: () => {
@ -62,43 +64,46 @@ export function useLogin() {
useEffect(() => {
const count = async () => {
try {
const available = await getAvailable();
updateState({ availableSet: true, available: available !== 0 });
} catch (err) {
const available = await getAvailable()
updateState({ availableSet: true, available: available !== 0 })
}
catch(err) {
console.log(err);
}
};
}
count();
// eslint-disable-next-line
}, []);
}, [])
useEffect(() => {
const { strings, menuStyle } = settings.state;
updateState({ strings, menuStyle });
}, [settings.state]);
const access = async (token) => {
const access = async (token) => {
if (!state.busy) {
updateState({ busy: true });
try {
await app.actions.access(token);
} catch (err) {
}
catch (err) {
console.log(err);
updateState({ busy: false });
throw new Error('access failed: check your token');
}
updateState({ busy: false });
}
};
}
useEffect(() => {
let params = new URLSearchParams(search);
let token = params.get('access');
let token = params.get("access");
if (token) {
access(token);
}
// eslint-disable-next-line
}, []);
}, [])
return { state, actions };
}

View File

@ -1,9 +1,10 @@
import { useContext, useState, useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useNavigate, useLocation } from "react-router-dom";
import { AppContext } from 'context/AppContext';
import { SettingsContext } from 'context/SettingsContext';
export function useAccess() {
const [state, setState] = useState({
display: null,
scheme: null,
@ -12,7 +13,7 @@ export function useAccess() {
themes: [],
language: null,
languages: [],
strings: {} as Record<string, string>,
strings: {} as Record<string,string>,
});
const navigate = useNavigate();
@ -22,7 +23,7 @@ export function useAccess() {
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
};
}
useEffect(() => {
if (app.state.status || app.state.adminToken) {
@ -31,21 +32,23 @@ export function useAccess() {
}, [app.state, navigate]);
useEffect(() => {
let params = new URLSearchParams(location + '');
let token = params.get('access');
let params = new URLSearchParams(location+"");
let token = params.get("access");
if (token) {
const access = async () => {
try {
await app.actions.access(token);
} catch (err) {
await app.actions.access(token)
}
catch (err) {
console.log(err);
}
};
}
access();
}
// eslint-disable-next-line
}, [navigate, location]);
useEffect(() => {
const { theme, themes, strings, language, languages, colors, display, scheme } = settings.state;
updateState({ theme, themes, language, languages, strings, colors, display, scheme });
@ -62,3 +65,4 @@ export function useAccess() {
return { state, actions };
}

View File

@ -2,13 +2,14 @@ import { checkResponse, fetchWithCustomTimeout } from './fetchUtil';
var base64 = require('base-64');
export async function addAccount(username, password, token) {
let access = '';
let access = "";
if (token) {
access = `?token=${token}`;
access = `?token=${token}`
}
let headers = new Headers();
headers.append('Credentials', 'Basic ' + base64.encode(username + ':' + password));
let profile = await fetchWithCustomTimeout(`/account/profile${access}`, { method: 'POST', headers: headers }, 60000);
let headers = new Headers()
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
let profile = await fetchWithCustomTimeout(`/account/profile${access}`, { method: 'POST', headers: headers }, 60000)
checkResponse(profile);
return await profile.json();
return await profile.json()
}

View File

@ -1,9 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addAccountAccess(token, accountId) {
let access = await fetchWithTimeout(`/admin/accounts/${accountId}/auth?token=${encodeURIComponent(token)}`, {
method: 'POST',
});
let access = await fetchWithTimeout(`/admin/accounts/${accountId}/auth?token=${encodeURIComponent(token)}`, { method: 'POST' })
checkResponse(access);
return await access.json();
return await access.json()
}

View File

@ -1,7 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addAccountCreate(token) {
let access = await fetchWithTimeout(`/admin/accounts?token=${encodeURIComponent(token)}`, { method: 'POST' });
let access = await fetchWithTimeout(`/admin/accounts?token=${encodeURIComponent(token)}`, { method: 'POST' })
checkResponse(access);
return await access.json();
return await access.json()
}

View File

@ -1,9 +1,10 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addCall(token, cardId) {
let param = '?agent=' + token;
let param = "?agent=" + token
let call = await fetchWithTimeout('/talk/calls' + param, { method: 'POST', body: JSON.stringify(cardId) });
checkResponse(call);
let ret = await call.json();
checkResponse(call)
let ret = await call.json()
return ret;
}

View File

@ -1,7 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addCard(token, message) {
let card = await fetchWithTimeout(`/contact/cards?agent=${token}`, { method: 'POST', body: JSON.stringify(message) });
let card = await fetchWithTimeout(`/contact/cards?agent=${token}`, { method: 'POST', body: JSON.stringify(message)} );
checkResponse(card);
return await card.json();
}

View File

@ -1,11 +1,9 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addChannel(token, type, cards, data) {
export async function addChannel(token, type, cards, data ) {
let params = { dataType: type, data: JSON.stringify(data), groups: [], cards };
let channel = await fetchWithTimeout(`/content/channels?agent=${token}`, {
method: 'POST',
body: JSON.stringify(params),
});
let channel = await fetchWithTimeout(`/content/channels?agent=${token}`, { method: 'POST', body: JSON.stringify(params)} );
checkResponse(channel);
return await channel.json();
}

View File

@ -1,34 +1,29 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addChannelTopic(token, channelId, datatype, message, assets) {
if (message == null && (assets == null || assets.length === 0)) {
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}`, {
method: 'POST',
body: JSON.stringify({}),
});
checkResponse(topic);
let slot = await topic.json();
return slot.id;
} else if (assets == null || assets.length === 0) {
let subject = {
data: JSON.stringify(message, (key, value) => {
if (value !== null) return value;
}),
datatype,
};
export async function addChannelTopic(token, channelId, datatype, message, assets ) {
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}&confirm=true`, {
method: 'POST',
body: JSON.stringify(subject),
});
if (message == null && (assets == null || assets.length === 0)) {
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}`,
{ method: 'POST', body: JSON.stringify({}) });
checkResponse(topic);
let slot = await topic.json();
return slot.id;
} else {
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}`, {
method: 'POST',
body: JSON.stringify({}),
});
}
else if (assets == null || assets.length === 0) {
let subject = { data: JSON.stringify(message, (key, value) => {
if (value !== null) return value
}), datatype };
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}&confirm=true`,
{ method: 'POST', body: JSON.stringify(subject) });
checkResponse(topic);
let slot = await topic.json();
return slot.id;
}
else {
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}`,
{ method: 'POST', body: JSON.stringify({}) });
checkResponse(topic);
let slot = await topic.json();
@ -38,74 +33,61 @@ export async function addChannelTopic(token, channelId, datatype, message, asset
if (asset.image) {
const formData = new FormData();
formData.append('asset', asset.image);
let transform = encodeURIComponent(JSON.stringify(['ithumb;photo', 'icopy;photo']));
let topicAsset = await fetch(
`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["ithumb;photo", "icopy;photo"]));
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
message.assets.push({
image: {
thumb: assetEntry.find((item) => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find((item) => item.transform === 'icopy;photo').assetId,
},
thumb: assetEntry.find(item => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find(item => item.transform === 'icopy;photo').assetId,
}
});
} else if (asset.video) {
}
else if (asset.video) {
const formData = new FormData();
formData.append('asset', asset.video);
let thumb = 'vthumb;video;' + asset.position;
let transform = encodeURIComponent(JSON.stringify(['vlq;video', 'vhd;video', thumb]));
let topicAsset = await fetch(
`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["vlq;video", "vhd;video", thumb]));
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
message.assets.push({
video: {
thumb: assetEntry.find((item) => item.transform === thumb).assetId,
lq: assetEntry.find((item) => item.transform === 'vlq;video').assetId,
hd: assetEntry.find((item) => item.transform === 'vhd;video').assetId,
},
thumb: assetEntry.find(item => item.transform === thumb).assetId,
lq: assetEntry.find(item => item.transform === 'vlq;video').assetId,
hd: assetEntry.find(item => item.transform === 'vhd;video').assetId,
}
});
} else if (asset.audio) {
}
else if (asset.audio) {
const formData = new FormData();
formData.append('asset', asset.audio);
let transform = encodeURIComponent(JSON.stringify(['acopy;audio']));
let topicAsset = await fetch(
`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["acopy;audio"]));
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
message.assets.push({
audio: {
label: asset.label,
full: assetEntry.find((item) => item.transform === 'acopy;audio').assetId,
},
full: assetEntry.find(item => item.transform === 'acopy;audio').assetId,
}
});
}
}
let subject = {
data: JSON.stringify(message, (key, value) => {
if (value !== null) return value;
}),
datatype,
};
let unconfirmed = await fetchWithTimeout(
`/content/channels/${channelId}/topics/${slot.id}/subject?agent=${token}`,
{ method: 'PUT', body: JSON.stringify(subject) },
);
let subject = { data: JSON.stringify(message, (key, value) => {
if (value !== null) return value
}), datatype };
let unconfirmed = await fetchWithTimeout(`/content/channels/${channelId}/topics/${slot.id}/subject?agent=${token}`,
{ method: 'PUT', body: JSON.stringify(subject) });
checkResponse(unconfirmed);
let confirmed = await fetchWithTimeout(
`/content/channels/${channelId}/topics/${slot.id}/confirmed?agent=${token}`,
{ method: 'PUT', body: JSON.stringify('confirmed') },
);
let confirmed = await fetchWithTimeout(`/content/channels/${channelId}/topics/${slot.id}/confirmed?agent=${token}`,
{ method: 'PUT', body: JSON.stringify('confirmed') });
checkResponse(confirmed);
return slot.id;
}
}

View File

@ -1,39 +1,32 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addContactChannelTopic(server, token, channelId, datatype, message, assets) {
let host = '';
export async function addContactChannelTopic(server, token, channelId, datatype, message, assets ) {
let host = "";
if (server) {
host = `https://${server}`;
host = `https://${server}`
}
if (message == null && (assets == null || assets.length === 0)) {
let topic = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics?contact=${token}`, {
method: 'POST',
body: JSON.stringify({}),
});
let topic = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics?contact=${token}`,
{ method: 'POST', body: JSON.stringify({}) });
checkResponse(topic);
let slot = await topic.json();
return slot.id;
} else if (assets == null || assets.length === 0) {
let subject = {
data: JSON.stringify(message, (key, value) => {
if (value !== null) return value;
}),
datatype,
};
}
else if (assets == null || assets.length === 0) {
let subject = { data: JSON.stringify(message, (key, value) => {
if (value !== null) return value
}), datatype };
let topic = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics?contact=${token}&confirm=true`, {
method: 'POST',
body: JSON.stringify(subject),
});
let topic = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics?contact=${token}&confirm=true`,
{ method: 'POST', body: JSON.stringify(subject) });
checkResponse(topic);
let slot = await topic.json();
return slot.id;
} else {
let topic = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics?contact=${token}`, {
method: 'POST',
body: JSON.stringify({}),
});
}
else {
let topic = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics?contact=${token}`,
{ method: 'POST', body: JSON.stringify({}) });
checkResponse(topic);
let slot = await topic.json();
@ -43,74 +36,61 @@ export async function addContactChannelTopic(server, token, channelId, datatype,
if (asset.image) {
const formData = new FormData();
formData.append('asset', asset.image);
let transform = encodeURIComponent(JSON.stringify(['ithumb;photo', 'icopy;photo']));
let topicAsset = await fetch(
`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["ithumb;photo", "icopy;photo"]));
let topicAsset = await fetch(`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
message.assets.push({
image: {
thumb: assetEntry.find((item) => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find((item) => item.transform === 'icopy;photo').assetId,
},
thumb: assetEntry.find(item => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find(item => item.transform === 'icopy;photo').assetId,
}
});
} else if (asset.video) {
}
else if (asset.video) {
const formData = new FormData();
formData.append('asset', asset.video);
let thumb = 'vthumb;video;' + asset.position;
let transform = encodeURIComponent(JSON.stringify(['vhd;video', 'vlq;video', thumb]));
let topicAsset = await fetch(
`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`,
{ method: 'POST', body: formData },
);
let thumb = "vthumb;video;" + asset.position
let transform = encodeURIComponent(JSON.stringify(["vhd;video", "vlq;video", thumb]));
let topicAsset = await fetch(`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
message.assets.push({
video: {
thumb: assetEntry.find((item) => item.transform === thumb).assetId,
lq: assetEntry.find((item) => item.transform === 'vlq;video').assetId,
hd: assetEntry.find((item) => item.transform === 'vhd;video').assetId,
},
thumb: assetEntry.find(item => item.transform === thumb).assetId,
lq: assetEntry.find(item => item.transform === 'vlq;video').assetId,
hd: assetEntry.find(item => item.transform === 'vhd;video').assetId,
}
});
} else if (asset.audio) {
}
else if (asset.audio) {
const formData = new FormData();
formData.append('asset', asset.audio);
let transform = encodeURIComponent(JSON.stringify(['acopy;audio']));
let topicAsset = await fetch(
`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["acopy;audio"]));
let topicAsset = await fetch(`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
message.assets.push({
audio: {
label: asset.label,
full: assetEntry.find((item) => item.transform === 'acopy;audio').assetId,
},
full: assetEntry.find(item => item.transform === 'acopy;audio').assetId,
}
});
}
}
let subject = {
data: JSON.stringify(message, (key, value) => {
if (value !== null) return value;
}),
datatype,
};
let subject = { data: JSON.stringify(message, (key, value) => {
if (value !== null) return value
}), datatype };
let unconfirmed = await fetchWithTimeout(
`${host}/content/channels/${channelId}/topics/${slot.id}/subject?contact=${token}`,
{ method: 'PUT', body: JSON.stringify(subject) },
);
let unconfirmed = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics/${slot.id}/subject?contact=${token}`,
{ method: 'PUT', body: JSON.stringify(subject) });
checkResponse(unconfirmed);
let confirmed = await fetchWithTimeout(
`${host}/content/channels/${channelId}/topics/${slot.id}/confirmed?contact=${token}`,
{ method: 'PUT', body: JSON.stringify('confirmed') },
);
let confirmed = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics/${slot.id}/confirmed?contact=${token}`,
{ method: 'PUT', body: JSON.stringify('confirmed') });
checkResponse(confirmed);
return slot.id;
}
}

View File

@ -1,14 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addContactRing(server, token, call) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
host = `https://${server}`
}
let ring = await fetchWithTimeout(`${host}/talk/rings?contact=${token}`, {
method: 'POST',
body: JSON.stringify(call),
});
let ring = await fetchWithTimeout(`${host}/talk/rings?contact=${token}`, { method: 'POST', body: JSON.stringify(call) });
checkResponse(ring);
}

View File

@ -1,9 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function clearChannelCard(token, channelId, cardId) {
let channel = await fetchWithTimeout(`/content/channels/${channelId}/cards/${cardId}?agent=${token}`, {
method: 'DELETE',
});
export async function clearChannelCard(token, channelId, cardId ) {
let channel = await fetchWithTimeout(`/content/channels/${channelId}/cards/${cardId}?agent=${token}`, {method: 'DELETE'});
checkResponse(channel);
return await channel.json();
}

View File

@ -1,9 +1,11 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function clearLogin(token, all) {
console.log('LOGOUT: ', token, all);
console.log("LOGOUT: ", token, all);
const param = all ? '&all=true' : '';
const logout = await fetchWithTimeout(`/account/apps?agent=${token}${param}`, { method: 'DELETE' });
checkResponse(logout);
const param = all ? '&all=true' : ''
const logout = await fetchWithTimeout(`/account/apps?agent=${token}${param}`, { method: 'DELETE' })
checkResponse(logout)
}

View File

@ -2,9 +2,10 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
var base64 = require('base-64');
export async function createAccount(username, password) {
let headers = new Headers();
headers.append('Credentials', 'Basic ' + base64.encode(username + ':' + password));
let profile = await fetchWithTimeout('/account/profile', { method: 'POST', headers: headers });
let headers = new Headers()
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
let profile = await fetchWithTimeout("/account/profile", { method: 'POST', headers: headers })
checkResponse(profile);
return await profile.json();
return await profile.json()
}

View File

@ -7,25 +7,22 @@ export function createWebsocket(url) {
}
export function checkResponse(response) {
if (response.status >= 400 && response.status < 600) {
throw new Error(response.url + ' failed');
if(response.status >= 400 && response.status < 600) {
throw new Error(response.url + " failed");
}
}
export async function fetchWithTimeout(url, options): Promise<Response> {
export async function fetchWithTimeout(url, options):Promise<Response> {
return Promise.race([
fetch(url, options).catch((err) => {
throw new Error(url + ' failed');
}),
new Promise<Response>((_, reject) => setTimeout(() => reject(new Error(url + ' timeout')), TIMEOUT)),
fetch(url, options).catch(err => { throw new Error(url + ' failed'); }),
new Promise<Response>((_, reject) => setTimeout(() => reject(new Error(url + ' timeout')), TIMEOUT))
]);
}
export async function fetchWithCustomTimeout(url, options, timeout): Promise<Response> {
export async function fetchWithCustomTimeout(url, options, timeout):Promise<Response> {
return Promise.race([
fetch(url, options).catch((err) => {
throw new Error(url + ' failed');
}),
new Promise<Response>((_, reject) => setTimeout(() => reject(new Error(url + ' timeout')), timeout)),
fetch(url, options).catch(err => { throw new Error(url + ' failed'); }),
new Promise<Response>((_, reject) => setTimeout(() => reject(new Error(url + ' timeout')), timeout))
]);
}

View File

@ -1,3 +1,4 @@
export function getAccountImageUrl(token, accountId) {
return `/admin/accounts/${accountId}/image?token=${encodeURIComponent(token)}`;
return `/admin/accounts/${accountId}/image?token=${encodeURIComponent(token)}`
}

View File

@ -3,5 +3,6 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getAccountStatus(token) {
let status = await fetchWithTimeout('/account/status?agent=' + token, { method: 'GET' });
checkResponse(status);
return await status.json();
return await status.json()
}

View File

@ -1,7 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getAvailable() {
let available = await fetchWithTimeout('/account/available', { method: 'GET' });
checkResponse(available);
return await available.json();
let available = await fetchWithTimeout("/account/available", { method: 'GET' })
checkResponse(available)
return await available.json()
}

View File

@ -5,3 +5,4 @@ export async function getCardCloseMessage(token, cardId) {
checkResponse(message);
return await message.json();
}

View File

@ -1,8 +1,9 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getCardDetail(token, cardId) {
let param = '?agent=' + token;
let param = "?agent=" + token
let detail = await fetchWithTimeout(`/contact/cards/${cardId}/detail${param}`, { method: 'GET' });
checkResponse(detail);
return await detail.json();
return await detail.json()
}

View File

@ -1,3 +1,4 @@
export function getCardImageUrl(token, cardId, revision) {
return `/contact/cards/${cardId}/profile/image?agent=${token}&revision=${revision}`;
return `/contact/cards/${cardId}/profile/image?agent=${token}&revision=${revision}`
}

View File

@ -5,3 +5,4 @@ export async function getCardOpenMessage(token, cardId) {
checkResponse(message);
return await message.json();
}

View File

@ -3,5 +3,6 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getCardProfile(token, cardId) {
let profile = await fetchWithTimeout(`/contact/cards/${cardId}/profile?agent=${token}`, { method: 'GET' });
checkResponse(profile);
return await profile.json();
return await profile.json()
}

View File

@ -1,11 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getCards(token, revision) {
let param = 'agent=' + token;
let param = "agent=" + token
if (revision != null) {
param += '&revision=' + revision;
param += '&revision=' + revision
}
let cards = await fetchWithTimeout(`/contact/cards?${param}`, { method: 'GET' });
checkResponse(cards);
return await cards.json();
checkResponse(cards)
return await cards.json()
}

View File

@ -2,6 +2,7 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getChannelDetail(token, channelId) {
let detail = await fetchWithTimeout(`/content/channels/${channelId}/detail?agent=${token}`, { method: 'GET' });
checkResponse(detail);
return await detail.json();
checkResponse(detail)
return await detail.json()
}

View File

@ -2,6 +2,7 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getChannelSummary(token, channelId) {
let summary = await fetchWithTimeout(`/content/channels/${channelId}/summary?agent=${token}`, { method: 'GET' });
checkResponse(summary);
return await summary.json();
checkResponse(summary)
return await summary.json()
}

View File

@ -1,9 +1,9 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getChannelTopic(token, channelId, topicId) {
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics/${topicId}/detail?agent=${token}`, {
method: 'GET',
});
checkResponse(topic);
return await topic.json();
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics/${topicId}/detail?agent=${token}`,
{ method: 'GET' });
checkResponse(topic)
return await topic.json()
}

View File

@ -1,3 +1,4 @@
export function getChannelTopicAssetUrl(token, channelId, topicId, assetId) {
return `/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?agent=${token}`;
return `/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?agent=${token}`
}

View File

@ -1,29 +1,29 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getChannelTopics(token, channelId, revision, count, begin, end) {
let rev = '';
let rev = ''
if (revision != null) {
rev = `&revision=${revision}`;
rev = `&revision=${revision}`
}
let cnt = '';
let cnt = ''
if (count != null) {
cnt = `&count=${count}`;
cnt = `&count=${count}`
}
let bgn = '';
let bgn = ''
if (begin != null) {
bgn = `&begin=${begin}`;
bgn = `&begin=${begin}`
}
let edn = '';
let edn = ''
if (end != null) {
edn = `&end=${end}`;
edn = `&end=${end}`
}
let topics = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}${rev}${cnt}${bgn}${edn}`, {
method: 'GET',
});
checkResponse(topics);
return {
let topics = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}${rev}${cnt}${bgn}${edn}`,
{ method: 'GET' });
checkResponse(topics)
return {
marker: topics.headers.get('topic-marker'),
revision: topics.headers.get('topic-revision'),
topics: await topics.json(),
};
}
}

View File

@ -1,14 +1,15 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getChannels(token, revision) {
let param = '?agent=' + token;
let param = "?agent=" + token
if (revision != null) {
param += `&channelRevision=${revision}`;
param += `&channelRevision=${revision}`
}
let types = encodeURIComponent(JSON.stringify(['sealed', 'superbasic']));
param += `&types=${types}`;
let types = encodeURIComponent(JSON.stringify([ 'sealed', 'superbasic' ]));
param += `&types=${types}`
let channels = await fetchWithTimeout('/content/channels' + param, { method: 'GET' });
checkResponse(channels);
let ret = await channels.json();
checkResponse(channels)
let ret = await channels.json()
return ret;
}

View File

@ -1,13 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelDetail(server, token, channelId) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let detail = await fetchWithTimeout(`${host}/content/channels/${channelId}/detail?contact=${token}`, {
method: 'GET',
});
checkResponse(detail);
return await detail.json();
let detail = await fetchWithTimeout(`${host}/content/channels/${channelId}/detail?contact=${token}`, { method: 'GET' });
checkResponse(detail)
return await detail.json()
}

View File

@ -1,13 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelSummary(server, token, channelId) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let summary = await fetchWithTimeout(`${host}/content/channels/${channelId}/summary?contact=${token}`, {
method: 'GET',
});
checkResponse(summary);
return await summary.json();
let summary = await fetchWithTimeout(`${host}/content/channels/${channelId}/summary?contact=${token}`, { method: 'GET' });
checkResponse(summary)
return await summary.json()
}

View File

@ -1,15 +1,14 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelTopic(server, token, channelId, topicId) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let topic = await fetchWithTimeout(
`${host}/content/channels/${channelId}/topics/${topicId}/detail?contact=${token}`,
{ method: 'GET' },
);
checkResponse(topic);
return await topic.json();
let topic = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics/${topicId}/detail?contact=${token}`,
{ method: 'GET' });
checkResponse(topic)
return await topic.json()
}

View File

@ -1,8 +1,9 @@
export function getContactChannelTopicAssetUrl(server, token, channelId, topicId, assetId) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
return `${host}/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?contact=${token}`;
return `${host}/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?contact=${token}`
}

View File

@ -1,35 +1,34 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelTopics(server, token, channelId, revision, count, begin, end) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let rev = '';
let rev = ''
if (revision != null) {
rev = `&revision=${revision}`;
rev = `&revision=${revision}`
}
let cnt = '';
let cnt = ''
if (count != null) {
cnt = `&count=${count}`;
cnt = `&count=${count}`
}
let bgn = '';
let bgn = ''
if (begin != null) {
bgn = `&begin=${begin}`;
bgn = `&begin=${begin}`
}
let edn = '';
let edn = ''
if (end != null) {
edn = `&end=${end}`;
edn = `&end=${end}`
}
let topics = await fetchWithTimeout(
`${host}/content/channels/${channelId}/topics?contact=${token}${rev}${cnt}${bgn}${edn}`,
{ method: 'GET' },
);
checkResponse(topics);
let topics = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics?contact=${token}${rev}${cnt}${bgn}${edn}`,
{ method: 'GET' });
checkResponse(topics)
return {
marker: topics.headers.get('topic-marker'),
revision: topics.headers.get('topic-revision'),
topics: await topics.json(),
};
}
}

View File

@ -1,21 +1,22 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannels(server, token, viewRevision?, channelRevision?) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let param = '?contact=' + token;
let param = "?contact=" + token
if (viewRevision != null) {
param += '&viewRevision=' + viewRevision;
param += '&viewRevision=' + viewRevision
}
if (channelRevision != null) {
param += '&channelRevision=' + channelRevision;
param += '&channelRevision=' + channelRevision
}
let types = encodeURIComponent(JSON.stringify(['sealed', 'superbasic']));
param += `&types=${types}`;
let types = encodeURIComponent(JSON.stringify([ 'sealed', 'superbasic' ]));
param += `&types=${types}`
let channels = await fetchWithTimeout(`${host}/content/channels${param}`, { method: 'GET' });
checkResponse(channels);
return await channels.json();
checkResponse(channels)
return await channels.json()
}

View File

@ -1,12 +1,13 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactProfile(server, token) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let profile = await fetchWithTimeout(`${host}/profile/message?contact=${token}`, { method: 'GET' });
let profile = await fetchWithTimeout(`${host}/profile/message?contact=${token}`, { method: 'GET', });
checkResponse(profile);
return await profile.json();
return await profile.json()
}

View File

@ -1,11 +1,13 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getGroups(token, revision) {
let param = 'agent=' + token;
let param = "agent=" + token
if (revision != null) {
param += '&revision=' + revision;
param += '&revision=' + revision
}
let groups = await fetchWithTimeout(`/alias/groups?${param}`, { method: 'GET' });
checkResponse(groups);
return await groups.json();
checkResponse(groups)
return await groups.json()
}

View File

@ -8,3 +8,4 @@ export async function getListing(server, filter) {
checkResponse(listing);
return await listing.json();
}

View File

@ -1,8 +1,10 @@
export function getListingImageUrl(server, guid) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
return `${host}/account/listing/${guid}/image`;
return `${host}/account/listing/${guid}/image`
}

View File

@ -1,7 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getListingMessage(server, guid) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
@ -10,3 +10,4 @@ export async function getListingMessage(server, guid) {
checkResponse(listing);
return await listing.json();
}

View File

@ -5,3 +5,4 @@ export async function getNodeAccounts(token) {
checkResponse(accounts);
return await accounts.json();
}

View File

@ -5,3 +5,4 @@ export async function getNodeConfig(token) {
checkResponse(config);
return await config.json();
}

View File

@ -5,3 +5,4 @@ export async function getNodeStatus() {
checkResponse(status);
return await status.json();
}

View File

@ -2,6 +2,8 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getProfile(token) {
let profile = await fetchWithTimeout(`/profile?agent=${token}`, { method: 'GET' });
checkResponse(profile);
return await profile.json();
checkResponse(profile)
return await profile.json()
}

View File

@ -1,3 +1,4 @@
export function getProfileImageUrl(token, revision) {
return '/profile/image?agent=' + token + '&revision=' + revision;
return '/profile/image?agent=' + token + "&revision=" + revision
}

View File

@ -1,13 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getUsername(name, token) {
let access = '';
let access = "";
if (token) {
access = `&token=${token}`;
access = `&token=${token}`
}
let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name) + access, {
method: 'GET',
});
checkResponse(available);
return await available.json();
let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name) + access, { method: 'GET' })
checkResponse(available)
return await available.json()
}

View File

@ -1,7 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function keepCall(token, callId) {
let param = '?agent=' + token;
let param = "?agent=" + token
let call = await fetchWithTimeout(`/talk/calls/${callId}` + param, { method: 'PUT' });
checkResponse(call);
checkResponse(call)
}

View File

@ -1,8 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeAccount(token, accountId) {
let res = await fetchWithTimeout(`/admin/accounts/${accountId}?token=${encodeURIComponent(token)}`, {
method: 'DELETE',
});
let res = await fetchWithTimeout(`/admin/accounts/${accountId}?token=${encodeURIComponent(token)}`, { method: 'DELETE' })
checkResponse(res);
}

View File

@ -1,7 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeCall(token, callId) {
let param = '?agent=' + token;
let param = "?agent=" + token
let call = await fetchWithTimeout(`/talk/calls/${callId}` + param, { method: 'DELETE' });
checkResponse(call);
checkResponse(call)
}

View File

@ -1,7 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeCard(token, cardId) {
let card = await fetchWithTimeout(`/contact/cards/${cardId}?agent=${token}`, { method: 'DELETE' });
let card = await fetchWithTimeout(`/contact/cards/${cardId}?agent=${token}`, { method: 'DELETE' } );
checkResponse(card);
return await card.json();
}

View File

@ -1,6 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeChannel(token, channelId) {
let channel = await fetchWithTimeout(`/content/channels/${channelId}?agent=${token}`, { method: 'DELETE' });
let channel = await fetchWithTimeout(`/content/channels/${channelId}?agent=${token}`,
{ method: 'DELETE' });
checkResponse(channel);
}

View File

@ -1,8 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeChannelTopic(token, channelId, topicId) {
let channel = await fetchWithTimeout(`/content/channels/${channelId}/topics/${topicId}?agent=${token}`, {
method: 'DELETE',
});
let channel = await fetchWithTimeout(`/content/channels/${channelId}/topics/${topicId}?agent=${token}`,
{ method: 'DELETE' });
checkResponse(channel);
}

View File

@ -1,11 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeContactCall(server, token, callId) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
host = `https://${server}`
}
const call = await fetchWithTimeout(`${host}/talk/calls/${callId}?contact=${token}`, { method: 'DELETE' });
checkResponse(call);
}

View File

@ -1,11 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeContactChannel(server, token, channelId) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let channel = await fetchWithTimeout(`${host}/content/channels/${channelId}?contact=${token}`, { method: 'DELETE' });
let channel = await fetchWithTimeout(`${host}/content/channels/${channelId}?contact=${token}`,
{ method: 'DELETE' });
checkResponse(channel);
}

View File

@ -1,13 +1,12 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function removeContactChannelTopic(server, token, channelId, topicId) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let channel = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics/${topicId}?contact=${token}`, {
method: 'DELETE',
});
let channel = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics/${topicId}?contact=${token}`,
{ method: 'DELETE' });
checkResponse(channel);
}

View File

@ -1,10 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setAccountAccess(token, appName, appVersion, platform) {
let access = await fetchWithTimeout(
`/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}`,
{ method: 'PUT', body: JSON.stringify([]) },
);
checkResponse(access);
return await access.json();
let access = await fetchWithTimeout(`/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}`, { method: 'PUT', body: JSON.stringify([]) })
checkResponse(access)
return await access.json()
}

View File

@ -2,8 +2,9 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
var base64 = require('base-64');
export async function setAccountLogin(token, username, password) {
let headers = new Headers();
headers.append('Credentials', 'Basic ' + base64.encode(username + ':' + password));
let res = await fetchWithTimeout(`/account/login?agent=${token}`, { method: 'PUT', headers });
let headers = new Headers()
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
let res = await fetchWithTimeout(`/account/login?agent=${token}`, { method: 'PUT', headers })
checkResponse(res);
}

View File

@ -1,6 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setAccountSeal(token, seal) {
let res = await fetchWithTimeout('/account/seal?agent=' + token, { method: 'PUT', body: JSON.stringify(seal) });
let res = await fetchWithTimeout('/account/seal?agent=' + token, { method: 'PUT', body: JSON.stringify(seal) })
checkResponse(res);
}

View File

@ -1,6 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setAccountSearchable(token, flag) {
let res = await fetchWithTimeout('/account/searchable?agent=' + token, { method: 'PUT', body: JSON.stringify(flag) });
let res = await fetchWithTimeout('/account/searchable?agent=' + token, { method: 'PUT', body: JSON.stringify(flag) })
checkResponse(res);
}

View File

@ -1,9 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setAccountStatus(token, accountId, disabled) {
let res = await fetchWithTimeout(`/admin/accounts/${accountId}/status?token=${encodeURIComponent(token)}`, {
method: 'PUT',
body: JSON.stringify(disabled),
});
let res = await fetchWithTimeout(`/admin/accounts/${accountId}/status?token=${encodeURIComponent(token)}`, { method: 'PUT', body: JSON.stringify(disabled) })
checkResponse(res);
}

View File

@ -1,7 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setCardCloseMessage(server, message) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
@ -10,3 +10,4 @@ export async function setCardCloseMessage(server, message) {
checkResponse(status);
return await status.json();
}

View File

@ -1,7 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setCardOpenMessage(server, message) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
@ -10,3 +10,4 @@ export async function setCardOpenMessage(server, message) {
checkResponse(status);
return await status.json();
}

View File

@ -1,10 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setCardProfile(token, cardId, message) {
let profile = await fetchWithTimeout(`/contact/cards/${cardId}/profile?agent=${token}`, {
method: 'PUT',
body: JSON.stringify(message),
});
let profile = await fetchWithTimeout(`/contact/cards/${cardId}/profile?agent=${token}`, { method: 'PUT', body: JSON.stringify(message) });
checkResponse(profile);
return await profile.json();
return await profile.json()
}

View File

@ -1,28 +1,20 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setCardConnecting(token, cardId) {
let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}`, {
method: 'PUT',
body: JSON.stringify('connecting'),
});
let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}`, { method: 'PUT', body: JSON.stringify('connecting') } );
checkResponse(card);
return await card.json();
}
export async function setCardConnected(token, cardId, access, view, article, channel, profile) {
let card = await fetchWithTimeout(
`/contact/cards/${cardId}/status?agent=${token}&token=${access}&viewRevision=${view}&articleRevision=${article}&channelRevision=${channel}&profileRevision=${profile}`,
{ method: 'PUT', body: JSON.stringify('connected') },
);
let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}&token=${access}&viewRevision=${view}&articleRevision=${article}&channelRevision=${channel}&profileRevision=${profile}`, { method: 'PUT', body: JSON.stringify('connected') } );
checkResponse(card);
return await card.json();
}
export async function setCardConfirmed(token, cardId) {
let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}`, {
method: 'PUT',
body: JSON.stringify('confirmed'),
});
let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}`, { method: 'PUT', body: JSON.stringify('confirmed') } );
checkResponse(card);
return await card.json();
}

View File

@ -1,9 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setChannelCard(token, channelId, cardId) {
let channel = await fetchWithTimeout(`/content/channels/${channelId}/cards/${cardId}?agent=${token}`, {
method: 'PUT',
});
export async function setChannelCard(token, channelId, cardId ) {
let channel = await fetchWithTimeout(`/content/channels/${channelId}/cards/${cardId}?agent=${token}`, {method: 'PUT'});
checkResponse(channel);
return await channel.json();
}

View File

@ -1,11 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setChannelSubject(token, channelId, dataType, data) {
export async function setChannelSubject(token, channelId, dataType, data ) {
let params = { dataType, data: JSON.stringify(data) };
let channel = await fetchWithTimeout(`/content/channels/${channelId}/subject?agent=${token}`, {
method: 'PUT',
body: JSON.stringify(params),
});
let channel = await fetchWithTimeout(`/content/channels/${channelId}/subject?agent=${token}`, { method: 'PUT', body: JSON.stringify(params)} );
checkResponse(channel);
return await channel.json();
}

View File

@ -4,52 +4,45 @@ export async function setChannelTopicSubject(token, channelId, topicId, asset) {
if (asset.image) {
const formData = new FormData();
formData.append('asset', asset.image);
let transform = encodeURIComponent(JSON.stringify(['ithumb;photo', 'icopy;photo']));
let topicAsset = await fetch(
`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["ithumb;photo", "icopy;photo"]));
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
return {
image: {
thumb: assetEntry.find((item) => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find((item) => item.transform === 'icopy;photo').assetId,
},
thumb: assetEntry.find(item => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find(item => item.transform === 'icopy;photo').assetId,
}
};
} else if (asset.video) {
}
else if (asset.video) {
const formData = new FormData();
formData.append('asset', asset.video);
let thumb = 'vthumb;video;' + asset.position;
let transform = encodeURIComponent(JSON.stringify(['vlq;video', 'vhd;video', thumb]));
let topicAsset = await fetch(
`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["vlq;video", "vhd;video", thumb]));
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
return {
video: {
thumb: assetEntry.find((item) => item.transform === thumb).assetId,
lq: assetEntry.find((item) => item.transform === 'vlq;video').assetId,
hd: assetEntry.find((item) => item.transform === 'vhd;video').assetId,
},
thumb: assetEntry.find(item => item.transform === thumb).assetId,
lq: assetEntry.find(item => item.transform === 'vlq;video').assetId,
hd: assetEntry.find(item => item.transform === 'vhd;video').assetId,
}
};
} else if (asset.audio) {
}
else if (asset.audio) {
const formData = new FormData();
formData.append('asset', asset.audio);
let transform = encodeURIComponent(JSON.stringify(['acopy;audio']));
let topicAsset = await fetch(
`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["acopy;audio"]));
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
return {
audio: {
label: asset.label,
full: assetEntry.find((item) => item.transform === 'acopy;audio').assetId,
},
full: assetEntry.find(item => item.transform === 'acopy;audio').assetId,
}
};
}
}

View File

@ -1,16 +1,11 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setChannelTopicSubject(token, channelId, topicId, datatype, data) {
let subject = {
data: JSON.stringify(data, (key, value) => {
if (value !== null) return value;
}),
datatype,
};
let subject = { data: JSON.stringify(data, (key, value) => {
if (value !== null) return value
}), datatype };
let channel = await fetchWithTimeout(
`/content/channels/${channelId}/topics/${topicId}/subject?agent=${token}&confirm=true`,
{ method: 'PUT', body: JSON.stringify(subject) },
);
let channel = await fetchWithTimeout(`/content/channels/${channelId}/topics/${topicId}/subject?agent=${token}&confirm=true`,
{ method: 'PUT', body: JSON.stringify(subject) });
checkResponse(channel);
}

View File

@ -1,7 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setContactChannelTopicSubject(server, token, channelId, topicId, asset) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
@ -9,52 +9,45 @@ export async function setContactChannelTopicSubject(server, token, channelId, to
if (asset.image) {
const formData = new FormData();
formData.append('asset', asset.image);
let transform = encodeURIComponent(JSON.stringify(['ithumb;photo', 'icopy;photo']));
let topicAsset = await fetch(
`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["ithumb;photo", "icopy;photo"]));
let topicAsset = await fetch(`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
return {
image: {
thumb: assetEntry.find((item) => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find((item) => item.transform === 'icopy;photo').assetId,
},
thumb: assetEntry.find(item => item.transform === 'ithumb;photo').assetId,
full: assetEntry.find(item => item.transform === 'icopy;photo').assetId,
}
};
} else if (asset.video) {
}
else if (asset.video) {
const formData = new FormData();
formData.append('asset', asset.video);
let thumb = 'vthumb;video;' + asset.position;
let transform = encodeURIComponent(JSON.stringify(['vhd;video', 'vlq;video', thumb]));
let topicAsset = await fetch(
`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`,
{ method: 'POST', body: formData },
);
let thumb = "vthumb;video;" + asset.position
let transform = encodeURIComponent(JSON.stringify(["vhd;video", "vlq;video", thumb]));
let topicAsset = await fetch(`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
return {
video: {
thumb: assetEntry.find((item) => item.transform === thumb).assetId,
lq: assetEntry.find((item) => item.transform === 'vlq;video').assetId,
hd: assetEntry.find((item) => item.transform === 'vhd;video').assetId,
},
thumb: assetEntry.find(item => item.transform === thumb).assetId,
lq: assetEntry.find(item => item.transform === 'vlq;video').assetId,
hd: assetEntry.find(item => item.transform === 'vhd;video').assetId,
}
};
} else if (asset.audio) {
}
else if (asset.audio) {
const formData = new FormData();
formData.append('asset', asset.audio);
let transform = encodeURIComponent(JSON.stringify(['acopy;audio']));
let topicAsset = await fetch(
`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`,
{ method: 'POST', body: formData },
);
let transform = encodeURIComponent(JSON.stringify(["acopy;audio"]));
let topicAsset = await fetch(`${host}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`, { method: 'POST', body: formData });
checkResponse(topicAsset);
let assetEntry = await topicAsset.json();
return {
audio: {
label: asset.label,
full: assetEntry.find((item) => item.transform === 'acopy;audio').assetId,
},
full: assetEntry.find(item => item.transform === 'acopy;audio').assetId,
}
};
}
}

View File

@ -1,21 +1,16 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setContactChannelTopicSubject(server, token, channelId, topicId, datatype, data) {
let host = '';
let host = "";
if (server) {
host = `https://${server}`;
}
let subject = {
data: JSON.stringify(data, (key, value) => {
if (value !== null) return value;
}),
datatype,
};
let subject = { data: JSON.stringify(data, (key, value) => {
if (value !== null) return value
}), datatype };
let channel = await fetchWithTimeout(
`${host}/content/channels/${channelId}/topics/${topicId}/subject?contact=${token}&confirm=true`,
{ method: 'PUT', body: JSON.stringify(subject) },
);
let channel = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics/${topicId}/subject?contact=${token}&confirm=true`,
{ method: 'PUT', body: JSON.stringify(subject) });
checkResponse(channel);
}

View File

@ -3,13 +3,9 @@ var base64 = require('base-64');
export async function setLogin(username, password, appName, appVersion, userAgent) {
const platform = encodeURIComponent(userAgent);
let headers = new Headers();
headers.append('Authorization', 'Basic ' + base64.encode(username + ':' + password));
let login = await fetchWithTimeout(`/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}`, {
method: 'POST',
body: JSON.stringify([]),
headers: headers,
});
checkResponse(login);
return await login.json();
let headers = new Headers()
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
let login = await fetchWithTimeout(`/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}`, { method: 'POST', body: JSON.stringify([]), headers: headers })
checkResponse(login)
return await login.json()
}

View File

@ -2,9 +2,7 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setNodeConfig(token, config) {
let body = JSON.stringify(config);
let settings = await fetchWithTimeout(`/admin/config?setOpenAccess=true&token=${encodeURIComponent(token)}`, {
method: 'PUT',
body,
});
let settings = await fetchWithTimeout(`/admin/config?setOpenAccess=true&token=${encodeURIComponent(token)}`, { method: 'PUT', body });
checkResponse(settings);
}

View File

@ -4,3 +4,4 @@ export async function setNodeStatus(token) {
let status = await fetchWithTimeout(`/admin/status?token=${encodeURIComponent(token)}`, { method: 'PUT' });
checkResponse(status);
}

View File

@ -3,6 +3,7 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setProfileData(token, name, location, description) {
let data = { name: name, location: location, description: description };
let profile = await fetchWithTimeout(`/profile/data?agent=${token}`, { method: 'PUT', body: JSON.stringify(data) });
checkResponse(profile);
return await profile.json();
checkResponse(profile)
return await profile.json()
}

View File

@ -2,6 +2,7 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setProfileImage(token, image) {
let profile = await fetchWithTimeout(`/profile/image?agent=${token}`, { method: 'PUT', body: JSON.stringify(image) });
checkResponse(profile);
return await profile.json();
checkResponse(profile)
return await profile.json()
}

View File

@ -24,7 +24,7 @@ export const CarouselWrapper = styled.div`
height: 128px;
display: flex;
align-items: center;
justify-content: center;
justify-content: center;
color: #888888;
background-color: #eeeeee;
margin-left: 72px;
@ -71,8 +71,8 @@ export const CarouselWrapper = styled.div`
}
.arrow:hover {
opacity: 1;
}
opacity: 1;
}
.item {
margin-right: 32px;
@ -113,3 +113,4 @@ export const CarouselWrapper = styled.div`
object-fit: contain;
}
`;

View File

@ -3,64 +3,52 @@ import { CarouselWrapper } from './Carousel.styled';
import { CloseOutlined } from '@ant-design/icons';
import ReactResizeDetector from 'react-resize-detector';
interface Props {
pad?: any;
items?: any;
itemRenderer?: any;
itemRemove?: any;
pad?:any
items?:any
itemRenderer?:any
itemRemove?:any
}
export function Carousel({ pad, items, itemRenderer, itemRemove }: Props) {
export function Carousel({ pad, items, itemRenderer, itemRemove }:Props) {
const [slots, setSlots] = useState([]);
let carousel = useRef<any>();
const RemoveItem = ({ index }) => {
if (itemRemove) {
return (
<div
className="delitem"
onClick={() => itemRemove(index)}
>
<CloseOutlined />
</div>
);
return <div className="delitem" onClick={() => itemRemove(index)}><CloseOutlined /></div>
}
return <></>;
};
return <></>
}
useEffect(() => {
let assets = [];
for (let i = 0; i < items.length; i++) {
assets.push(
<ReactResizeDetector
handleWidth={true}
handleHeight={false}
>
assets.push((
<ReactResizeDetector handleWidth={true} handleHeight={false}>
{({ width, height }) => {
return (
<div className="item noselect">
<div className="asset">{itemRenderer(items[i], i)}</div>
<div className="asset">{ itemRenderer(items[i], i) }</div>
<RemoveItem index={i} />
</div>
);
}}
</ReactResizeDetector>,
);
</ReactResizeDetector>
));
}
if (items.length > 0) {
assets.push(<div className="space"></div>);
assets.push(<div className="space"></div>)
}
setSlots(assets);
}, [items, itemRenderer]);
return (
<CarouselWrapper>
<div
className="carousel"
style={{ paddingLeft: pad + 32 }}
ref={carousel}
>
<div className="carousel" style={{ paddingLeft: pad + 32 }} ref={carousel}>
{slots}
</div>
</CarouselWrapper>
);
}

View File

@ -2,15 +2,20 @@ import { useContext, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
export function useCarousel() {
const [state, setState] = useState({});
const [state, setState] = useState({
});
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
};
}
const navigate = useNavigate();
const actions = {};
const actions = {
};
return { state, actions };
}

View File

@ -21,7 +21,7 @@ export const Colors = {
itemDivider: '#eeeeee',
unsaved: '#ffff00',
unsaved: '#ffff00',
connected: '#44cc44',
connecting: '#dd88ff',
requested: '#4488ff',
@ -70,7 +70,7 @@ export const LightTheme = {
sectionBorder: '#bbbbbb',
headerBorder: '#aaaaaa',
drawerBorder: '#cccccc',
unsaved: '#ffff00',
unsaved: '#ffff00',
connected: '#44cc44',
connecting: '#dd88ff',
requested: '#4488ff',
@ -109,10 +109,11 @@ export const DarkTheme = {
sectionBorder: '#777777',
headerBorder: '#aaaaaa',
drawerBorder: '#444444',
unsaved: '#ffff00',
unsaved: '#ffff00',
connected: '#44cc44',
connecting: '#dd88ff',
requested: '#4488ff',
pending: '#22aaaa',
confirmed: '#aaaaaa',
};

View File

@ -14,7 +14,7 @@ export const en = {
newMessage: 'New Message',
topics: 'Topics',
unsetSealing: 'Unset Sealing Key',
newTopic: 'New Topic',
newTopic: 'New Topic',
noContacts: 'No Contacts',
noTopics: 'No Topics',
@ -65,7 +65,7 @@ export const en = {
password: 'Password',
newPassword: 'New Password',
confirmPassword: 'Confirm Password',
deleteKey: "Type 'delete' to remove key",
deleteKey: 'Type \'delete\' to remove key',
delete: 'delete',
remove: 'Delete',
username: 'Username',
@ -101,7 +101,7 @@ export const en = {
createAccount: 'Create Account',
accountLogin: 'Account Login',
toCreate: 'Accounts are created through a link generated from the admin dashboard.',
admin: 'Admin',
admin: 'Admin',
loginError: 'Login Error',
loginMessage: 'Please confirm your username and password.',
createError: 'Create Account Error',
@ -170,7 +170,7 @@ export const en = {
host: 'Host',
guest: 'Guest',
editSubject: 'Edit Subject',
editMembership: 'Edit Membership',
editMembership: 'Edit Membership',
deleteTopic: 'Delete Topic',
leaveTopic: 'Leave Topic',
@ -237,7 +237,7 @@ export const fr = {
node: 'Serveur',
location: 'Emplacement',
description: 'Description',
timeFormat: "Format de l'heure",
timeFormat: 'Format de l\'heure',
dateFormat: 'Format de la date',
theme: 'Thème',
language: 'Langue',
@ -255,10 +255,10 @@ export const fr = {
password: 'Mot de Passe',
newPassword: 'Nouveau Mot de Passe',
confirmPassword: 'Confirmer le Mot de Passe',
deleteKey: "Tapez 'supprimer' pour supprimer la clé",
deleteKey: 'Tapez \'supprimer\' pour supprimer la clé',
delete: 'supprimer',
remove: 'Supprimer',
username: "Nom d'Utilisateur",
username: 'Nom d\'Utilisateur',
updateProfile: 'Mettre à Jour le Profil',
syncError: 'Erreur de Synchronisation',
@ -290,13 +290,13 @@ export const fr = {
create: 'Créer',
createAccount: 'Créer un Compte',
accountLogin: 'Connexion au Compte',
toCreate: "Les comptes sont créés via un lien généré depuis le tableau de bord d'administration.",
toCreate: 'Les comptes sont créés via un lien généré depuis le tableau de bord d\'administration.',
admin: 'Administrateur',
loginError: 'Erreur de connexion',
loginMessage: "Veuillez confirmer votre nom d'utilisateur et votre mot de passe.",
loginMessage: 'Veuillez confirmer votre nom d\'utilisateur et votre mot de passe.',
createError: 'Erreur de création de compte',
createMessage: 'Veuillez vérifier auprès de votre administrateur.',
adminError: "Erreur d'Accès",
adminError: 'Erreur d\'Accès',
adminMessage: 'Veuillez confirmer votre mot de passe',
confirmDelete: 'Suppression de Compte',
@ -325,16 +325,16 @@ export const fr = {
allowUnsealed: 'Autoriser les Sujets non Sécurisés',
topicContent: 'Contenu du Sujet:',
enableImage: 'Activer les Images du Sujet',
imageHint: "Autoriser la publication d'images dans des sujets",
enableAudio: "Activer l'Audio du Suject",
audioHint: "Autoriser la publication d'audio dans des sujets",
imageHint: 'Autoriser la publication d\'images dans des sujets',
enableAudio: 'Activer l\'Audio du Suject',
audioHint: 'Autoriser la publication d\'audio dans des sujets',
enableVideo: 'Activer les Videos du Sujet',
videoHint: 'Autoriser la publication de video dans des sujets',
enableWeb: 'Activer les Appels WebRTC',
webHint: 'Autoriser les appels audio et vidéo aux contacts',
serverUrl: 'URL du Serveur WebRTC',
urlHint: 'turn:ip:port?transport=udp',
webUsername: "Nom d'Utilisateur WebRTC",
webUsername: 'Nom d\'Utilisateur WebRTC',
webPassword: 'Mot de Passe WebRTC',
failedLoad: 'Échec du Chargement',
limit: 'Limite',
@ -446,7 +446,7 @@ export const sp = {
password: 'Contraseña',
newPassword: 'Nueva Contraseña',
confirmPassword: 'Confirmar Contraseña',
deleteKey: "Escribe 'borrar' para Eliminar la Clave",
deleteKey: 'Escribe \'borrar\' para Eliminar la Clave',
delete: 'borrar',
remove: 'Eliminar',
username: 'Nombre de usuario',
@ -567,7 +567,7 @@ export const sp = {
confirmRemove: '¿Estás seguro de que quieres eliminar el contacto?',
message: 'Mensaje',
sealedMessage: 'Mensaje Seguro',
};
}
export const pt = {
code: 'pt',
@ -636,7 +636,7 @@ export const pt = {
password: 'Senha',
newPassword: 'Nova senha',
confirmPassword: 'Confirmar senha',
deleteKey: "Digite 'excluir' para deletar a chave",
deleteKey: 'Digite \'excluir\' para deletar a chave',
delete: 'excluir',
remove: 'Remover',
username: 'Nome de usuário',
@ -757,7 +757,7 @@ export const pt = {
confirmRemove: 'Tem certeza de que deseja remover o contato?',
message: 'Mensagem',
sealedMessage: 'Mensagem Segura',
};
}
export const de = {
code: 'de',
@ -826,7 +826,7 @@ export const de = {
password: 'Passwort',
newPassword: 'Neues Passwort',
confirmPassword: 'Passwort bestätigen',
deleteKey: "'löschen' eingeben, um den Schlüssel zu löschen",
deleteKey: '\'löschen\' eingeben, um den Schlüssel zu löschen',
delete: 'löschen',
remove: 'Entfernen',
username: 'Benutzername',
@ -947,7 +947,7 @@ export const de = {
confirmRemove: 'Sind Sie sicher, dass Sie den Kontakt löschen möchten?',
message: 'Nachricht',
sealedMessage: 'Gesicherte Nachricht',
};
}
export const ru = {
code: 'ru',
@ -1016,7 +1016,7 @@ export const ru = {
password: 'Пароль',
newPassword: 'Новый пароль',
confirmPassword: 'Подтвердите пароль',
deleteKey: "Введите 'удалить', чтобы удалить ключ",
deleteKey: 'Введите \'удалить\', чтобы удалить ключ',
delete: 'удалить',
remove: 'Удалить',
username: 'Имя пользователя',
@ -1137,4 +1137,4 @@ export const ru = {
confirmRemove: 'Вы уверены, что хотите удалить контакт?',
message: 'Cообщение',
sealedMessage: 'Защищенное Cообщение',
};
}

View File

@ -5,5 +5,10 @@ export const AccountContext = createContext(defaultAccountContext);
export function AccountContextProvider({ children }) {
const { state, actions } = useAccountContext();
return <AccountContext.Provider value={{ state, actions }}>{children}</AccountContext.Provider>;
return (
<AccountContext.Provider value={{ state, actions }}>
{children}
</AccountContext.Provider>
);
}

View File

@ -5,5 +5,10 @@ export const AppContext = createContext(defaultAppContext);
export function AppContextProvider({ children }) {
const { state, actions } = useAppContext();
return <AppContext.Provider value={{ state, actions }}>{children}</AppContext.Provider>;
return (
<AppContext.Provider value={{ state, actions }}>
{children}
</AppContext.Provider>
);
}

View File

@ -5,5 +5,10 @@ export const CardContext = createContext(defaultCardContext);
export function CardContextProvider({ children }) {
const { state, actions } = useCardContext();
return <CardContext.Provider value={{ state, actions }}>{children}</CardContext.Provider>;
return (
<CardContext.Provider value={{ state, actions }}>
{children}
</CardContext.Provider>
);
}

View File

@ -5,5 +5,10 @@ export const ChannelContext = createContext(defaultChannelContext);
export function ChannelContextProvider({ children }) {
const { state, actions } = useChannelContext();
return <ChannelContext.Provider value={{ state, actions }}>{children}</ChannelContext.Provider>;
return (
<ChannelContext.Provider value={{ state, actions }}>
{children}
</ChannelContext.Provider>
);
}

View File

@ -5,5 +5,10 @@ export const ConversationContext = createContext(defaultConversionContext);
export function ConversationContextProvider({ children }) {
const { state, actions } = useConversationContext();
return <ConversationContext.Provider value={{ state, actions }}>{children}</ConversationContext.Provider>;
return (
<ConversationContext.Provider value={{ state, actions }}>
{children}
</ConversationContext.Provider>
);
}

View File

@ -5,5 +5,10 @@ export const ProfileContext = createContext(defaultProfileContext);
export function ProfileContextProvider({ children }) {
const { state, actions } = useProfileContext();
return <ProfileContext.Provider value={{ state, actions }}>{children}</ProfileContext.Provider>;
return (
<ProfileContext.Provider value={{ state, actions }}>
{children}
</ProfileContext.Provider>
);
}

Some files were not shown because too many files have changed in this diff Show More