Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
nkcr committed Jun 7, 2022
2 parents e6068a9 + b77f05e commit 7638273
Show file tree
Hide file tree
Showing 17 changed files with 255 additions and 95 deletions.
18 changes: 18 additions & 0 deletions docs/frontend_doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,24 @@ Return:
`123.456.9%3A9000`. The native javascript functions `decodeURIComponent` and
`encodeURIComponent` can be used.

## Get the default proxy address

| | |
|--------|---------------------|
| URL | `/api/config/proxy` |
| Method | `GET` |
| Input | |


Return:

`200 OK` `text/plain`

```
http://example.com/
```


# Production settings

The two followings things that will be shown here is how to have https on the different webpages and how to make the app run on a on server.
Expand Down
46 changes: 33 additions & 13 deletions web/frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2",
"@testing-library/react": "^13.3.0",
"@types/enzyme": "^3.10.11",
"@types/file-saver": "^2.0.5",
"@types/node": "^17.0.16",
Expand Down
11 changes: 8 additions & 3 deletions web/frontend/src/components/utils/Endpoints.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ export const getProxyAddress = (NodeAddr: string) => `/api/proxies/${encodeURICo
export const getProxiesAddresses = '/api/proxies';

// public information can be directly fetched from dela nodes
export const election = (ElectionID: string) =>
`${process.env.REACT_APP_PROXY}/evoting/elections/${ElectionID}`;
export const elections = `${process.env.REACT_APP_PROXY}/evoting/elections`;
export const election = (proxy: string, ElectionID: string) =>
new URL(`/evoting/elections/${ElectionID}`, proxy).href;
export const elections = (proxy: string) => {
return new URL('/evoting/elections', proxy).href;
};

// get the default proxy address
export const getProxyConfig = '/api/config/proxy';

// To remove
export const ENDPOINT_EVOTING_RESULT = '/api/evoting/result';
104 changes: 104 additions & 0 deletions web/frontend/src/components/utils/proxy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { CheckIcon, PencilIcon, RefreshIcon } from '@heroicons/react/outline';
import { FlashContext, FlashLevel, ProxyContext } from 'index';
import { ChangeEvent, FC, createRef, useContext, useEffect, useState } from 'react';
import * as endpoints from './Endpoints';

const proxyKey = 'proxy';

const ProxyInput: FC = () => {
const fctx = useContext(FlashContext);
const pctx = useContext(ProxyContext);

const [proxy, setProxy] = useState<string>(pctx.getProxy());
const [inputVal, setInputVal] = useState('');
const [inputChanging, setInputChanging] = useState(false);
const [inputWidth, setInputWidth] = useState(0);

const proxyTextRef = createRef<HTMLDivElement>();

const fetchFromBackend = async () => {
try {
const response = await fetch(endpoints.getProxyConfig);
if (!response.ok) {
const js = await response.json();
throw new Error(JSON.stringify(js));
} else {
setProxy(await response.text());
}
} catch (e) {
fctx.addMessage(`Failed to get proxy: ${proxy}`, FlashLevel.Error);
}
};

// update the proxy context and sessionStore each time the proxy changes
useEffect(() => {
sessionStorage.setItem(proxyKey, proxy);
pctx.setProxy(proxy);
setInputVal(proxy);
}, [proxy]);

// function called by the "refresh" button
const getDefault = () => {
fetchFromBackend();
fctx.addMessage('Proxy updated to default', FlashLevel.Info);
};

const updateProxy = () => {
try {
new URL(inputVal);
} catch {
fctx.addMessage('invalid URL', FlashLevel.Error);
return;
}

setInputChanging(false);
setProxy(inputVal);
};

const editProxy = () => {
setInputWidth(proxyTextRef.current.clientWidth);
setInputChanging(true);
};

return (
<div className="flex flex-row items-center">
{inputChanging ? (
<>
<input
value={inputVal}
onChange={(e: ChangeEvent<HTMLInputElement>) => setInputVal(e.target.value)}
className="mt-1 ml-3 border rounded-md p-2"
style={{ width: `${inputWidth + 3}px` }}
/>
<div className="ml-1">
<button className={`border p-1 rounded-md }`} onClick={updateProxy}>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</button>
</div>
</>
) : (
<>
<div
ref={proxyTextRef}
className="mt-1 ml-3 border border-transparent p-2"
onClick={editProxy}>
{inputVal}
</div>
<div className="">
<button className="hover:text-indigo-500 p-1 rounded-md" onClick={editProxy}>
<PencilIcon className="m-1 h-3 w-3" aria-hidden="true" />
</button>
</div>
</>
)}
<button
onClick={getDefault}
className="flex flex-row items-center hover:text-indigo-500 p-1 rounded-md">
get default
<RefreshIcon className="m-1 h-3 w-3" aria-hidden="true" />
</button>
</div>
);
};

export default ProxyInput;
9 changes: 8 additions & 1 deletion web/frontend/src/components/utils/useElection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ import useFetchCall from './useFetchCall';
import * as endpoints from './Endpoints';
import { useFillElectionInfo } from './FillElectionInfo';
import { ID } from 'types/configuration';
import { useContext } from 'react';
import { ProxyContext } from 'index';

// Custom hook that fetches an election given its id and returns its
// different parameters
const useElection = (electionID: ID) => {
const pctx = useContext(ProxyContext);

const request = {
method: 'GET',
};
const [data, loading, error] = useFetchCall(endpoints.election(electionID), request);
const [data, loading, error] = useFetchCall(
endpoints.election(pctx.getProxy(), electionID),
request
);
const {
status,
setStatus,
Expand Down
47 changes: 46 additions & 1 deletion web/frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import App from 'layout/App';
import reportWebVitals from 'reportWebVitals';
import ShortUniqueId from 'short-unique-id';

import * as endpoints from 'components/utils/Endpoints';

const flashTimeout = 4000;

// By default we load the mock messages when not in production. This is handy
Expand Down Expand Up @@ -71,6 +73,28 @@ class FlashMessage {
// the flash context handles flash messages across the app
export const FlashContext = createContext<FlashState>(undefined);

// the proxy state provides the proxy address across all the app
export interface ProxyState {
getProxy(): string;
setProxy(p: string);
}

export class ProxyHolder implements ProxyState {
proxy: string;

getProxy(): string {
return this.proxy;
}

setProxy(p: string) {
this.proxy = p;
}
}

const defaultProxyState = new ProxyHolder();

export const ProxyContext = createContext<ProxyState>(defaultProxyState);

// A small elements to display that the page is loading, should be something
// more elegant in the future and be its own component.
const Loading: FC = () => (
Expand Down Expand Up @@ -159,6 +183,22 @@ const AppContainer = () => {
},
};

const setDefaultProxy = async () => {
let proxy = sessionStorage.getItem('proxy');

if (proxy === null) {
const response = await fetch(endpoints.getProxyConfig);
if (!response.ok) {
const js = await response.json();
throw new Error(`Failed to get the default proxy: ${JSON.stringify(js)}`);
}

proxy = await response.text();
}

defaultProxyState.setProxy(proxy);
};

useEffect(() => {
const req = {
method: 'GET',
Expand All @@ -182,6 +222,9 @@ const AppContainer = () => {
role: result.role,
});

// wait for the default proxy to be set
await setDefaultProxy();

setContent(<App />);
} catch (e) {
setContent(<Failed>{e.toString()}</Failed>);
Expand All @@ -194,7 +237,9 @@ const AppContainer = () => {

return (
<FlashContext.Provider value={flashState}>
<AuthContext.Provider value={auth}>{content}</AuthContext.Provider>
<AuthContext.Provider value={auth}>
<ProxyContext.Provider value={defaultProxyState}>{content}</ProxyContext.Provider>
</AuthContext.Provider>
</FlashContext.Provider>
);
};
Expand Down
2 changes: 1 addition & 1 deletion web/frontend/src/language/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"delete": "Delete",
"combineShares": "Combine shares",
"createElec": "Create election",
"clearElec": "Clear election",
"clearElection": "Clear election",
"elecName": "Election title",
"confirmRemovesubject": "Do you really want to remove this subject?",
"confirmRemovetext": "Do you really want to remove this text?",
Expand Down
7 changes: 6 additions & 1 deletion web/frontend/src/layout/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import ProxyInput from 'components/utils/proxy';

const Footer = () => (
<div className="flex flex-row border-t justify-center bg-white items-center w-full p-4 text-gray-300 text-xs">
<footer>
<div className="max-w-7xl mx-auto py-2 px-4 overflow-hidden sm:px-6 lg:px-8">
<div className="flex flex-row items-center max-w-7xl mx-auto py-2 px-4 overflow-hidden sm:px-6 lg:px-8">
<span className="text-gray-400"> &copy; 2022 DEDIS LAB - </span>
<a className="text-gray-600" href="https://github.com/dedis/dela">
https://github.com/dedis/dela
</a>
<div className="px-10">
<ProxyInput />
</div>
</div>
</footer>
</div>
Expand Down
Loading

0 comments on commit 7638273

Please sign in to comment.