Π·Π΅Ρ€ΠΊΠ°Π»ΠΎ ΠΈΠ·
1
0
Π€ΠΎΡ€ΠΊΠ½ΡƒΡ‚ΡŒ 0
* πŸ—‘ Remove result app

- Steps towards moving to a single demo app. 
- Removing result app in favor of a single app to demonstrate electionguard

* βœ… Remove port exposure
This commit is contained in:
Keith Fung 2022-02-01 10:07:12 -05:00 ΠΊΠΎΠΌΠΌΠΈΡ‚ ΠΏΡ€ΠΎΠΈΠ·Π²Ρ‘Π» GitHub
Π ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒ 2693950ce4
ΠšΠΎΠΌΠΌΠΈΡ‚ cd13d80da3
НС Π½Π°ΠΉΠ΄Π΅Π½ ΠΊΠ»ΡŽΡ‡, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Π΄Π°Π½Π½ΠΎΠΉ подписи
Π˜Π΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΊΠ»ΡŽΡ‡Π° GPG: 4AEE18F83AFDEB23
67 ΠΈΠ·ΠΌΠ΅Π½Ρ‘Π½Π½Ρ‹Ρ… Ρ„Π°ΠΉΠ»ΠΎΠ²: 4 Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΉ ΠΈ 1883 ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠΉ

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -5,12 +5,5 @@ docs
Dockerfile
build
node_modules
storybook-static
packages/api/dist
packages/api/node_modules
packages/library/build
packages/library/node_modules
packages/admin-app/build
packages/admin-app/node_modules
packages/result-app/build
packages/result-app/node_modules

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -2,7 +2,6 @@
# build
build
storybook-static
tsconfig.tsbuildinfo
# dependencies

3
.vscode/settings.json поставляСмый
ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -4,7 +4,6 @@
"javascript.format.enable": false,
"eslint.workingDirectories": [
{ "directory": "packages/admin-app", "changeProcessCWD": true },
{ "directory": "packages/api-client", "changeProcessCWD": true },
{ "directory": "packages/result-app", "changeProcessCWD": true }
{ "directory": "packages/api-client", "changeProcessCWD": true }
]
}

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -13,7 +13,6 @@ RUN lerna bootstrap
RUN lerna run build
RUN lerna run build-storybook
RUN yarn global add serve
EXPOSE 4500

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -12,5 +12,4 @@ RUN lerna bootstrap
RUN lerna run build
EXPOSE 3001
EXPOSE 3002
CMD ["lerna", "run", "start"]

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,4 +1,4 @@
.PHONY: all install build start test lint admin-app result-app storybook build-storybook start-with-storybook npm-version npm-publish docker-dev-app docker-dev-storybook docker-dev-all
.PHONY: all install build start test lint admin-app npm-version npm-publish docker-dev-app docker-dev-all
all: install lint build test
@ -22,9 +22,6 @@ lint:
admin-app:
npm run admin-app
result-app:
npm run result-app
# Packaging
npm-version:
npm run npm-version

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -13,7 +13,6 @@ This repository is a "reference implementation" of ElectionGuard UI written usin
| [`packages`](packages) | Monorepo packages for this project |
| [`package/admin-app`](/packages/admin-app) | sample UI for an admin website |
| [`packages/api-client`](packages/api-client) | library for connecting to api backend |
| [`packages/result-app`](packages/result-app) | sample UI for election result website |
| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Guidelines for contributing |
| [`README.md`](README.md) | This README file |
| [`LICENSE`](LICENSE) | The license for ElectionGuard-Python. |
@ -26,7 +25,7 @@ Learn More in the [ElectionGuard Repository](https://github.com/microsoft/electi
## 🦸 How Can I use ElectionGuard?
ElectionGuard supports a variety of use cases. The Primary use case is to generate verifiable end-to-end (E2E) encrypted elections. The Electionguard process can also be used for other use cases such as privacy enhanced risk-limiting audits (RLAs).
ElectionGuard supports a variety of use cases. The Primary use case is to generate verifiable end-to-end (E2E) encrypted elections. The ElectionGuard process can also be used for other use cases such as privacy enhanced risk-limiting audits (RLAs).
## πŸ’» Requirements
@ -96,7 +95,7 @@ make test
#### Applications
Runs the apps in development mode. Open the Admin App at [http://localhost:3001](http://localhost:3001) or the Result App at [http://localhost:3002](http://localhost:3002) to view them in the browser.
Runs the apps in development mode. Open the Admin App at [http://localhost:3001](http://localhost:3001) to view in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
@ -111,20 +110,6 @@ Runs only the admin application.
make admin-app
```
Runs only the result application.
```
make result-app
```
#### Storybook
Runs the app in the storybook mode. Open [http://localhost:6006](http://localhost:6006) to view it in the browser. The page will reload if you make edits. You will also see any lint errors in the console.
```
make storybook
```
#### Docker
A local docker image will be created to run the admin website instead of running it directly like the 'make start' command above.
@ -133,12 +118,6 @@ A local docker image will be created to run the admin website instead of running
make docker-dev-app
```
A local docker image will be created to run the storybook website instead of running it directly like the 'make storybook' command above.
```
make docker-dev-storybook
```
## Contributing
This project encourages community contributions for development, testing, documentation, code review, and performance analysis, etc. For more information on how to contribute, see [the contribution guidelines][contributing]

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -12,16 +12,3 @@ services:
# https://github.com/facebook/create-react-app/issues/8688
stdin_open: true
command: 'serve -l 3001 packages/admin-app/build'
result-app:
build:
dockerfile: ./Dockerfile
context: .
ports:
- 3002:3002
volumes:
- '.:/app'
- '/app/node_modules'
# https://github.com/facebook/create-react-app/issues/8688
stdin_open: true
command: 'serve -l 3002 packages/result-app/build'

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -6,9 +6,7 @@
],
"scripts": {
"start": "lerna run start --parallel",
"start-with-storybook": "npm storybook && npm run start",
"admin-app": "lerna run start --scope=@electionguard-ui/admin-app",
"result-app": "lerna run start --scope=@electionguard-ui/result-app",
"build": "lerna run build --stream",
"test": "lerna run test --parallel",
"lint": "lerna run lint --parallel",
@ -16,7 +14,6 @@
"bundle": "lerna run bundle --parallel",
"clean": "lerna clean --yes",
"bootstrap": "npm run clean && lerna bootstrap",
"storybook": "lerna run storybook",
"npm-publish": "lerna run npm-publish",
"npm-version": "lerna run npm-version-patch"
},

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,2 +0,0 @@
SKIP_PREFLIGHT_CHECK=true
PORT=3002

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,3 +0,0 @@
REACT_APP_MEDIATOR_SERVICE=http://localhost:8000/api/v1/
REACT_APP_GUARDIAN_SERVICE=http://localhost:8001/api/v1/
REACT_APP_MOCK_ENABLED=false

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,3 +0,0 @@
{
"extends": "../../.eslintrc.json"
}

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,54 +0,0 @@
{
"name": "@electionguard-ui/result-app",
"description": "Result application for displaying electionguard results",
"author": "electionguard",
"license": "MIT",
"repository": "microsoft/electionguard-ui",
"version": "0.1.2",
"private": true,
"dependencies": {
"@electionguard/api-client": "0.1.2",
"@formatjs/intl": "^1.14.2",
"@material-ui/core": "^4.12.3",
"@material-ui/data-grid": "^4.0.0-alpha.29",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.15.1",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^27.0.3",
"@types/node": "^12.0.0",
"@types/react": "17.0.2",
"@types/react-dom": "17.0.2",
"babel-loader": "8.1.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-intl": "^5.21.0",
"react-query": "^3.29.0",
"react-router": "^5.2.1",
"react-router-dom": "^6.1.1",
"react-scripts": "^5.0.0",
"typescript": "^4.3.5",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --watchAll=false",
"lint": "npm run eslint && npm run prettier",
"lint:fix": "npm run eslint --fix && npm run prettier --write",
"eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
"prettier": "prettier --check '{src,public}/**/*.{js,jsx,ts,tsx,css,html,svg}' --no-error-on-unmatched-pattern"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Π”Π²ΠΎΠΈΡ‡Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅
packages/result-app/public/favicon.ico

Π”Π²ΠΎΠΈΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Π½Π΅ отобраТаСтся.

Π”ΠΎ

Π¨ΠΈΡ€ΠΈΠ½Π°:  |  Высота:  |  Π Π°Π·ΠΌΠ΅Ρ€: 3.8 KiB

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,39 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
--></body>
</html>

Π”Π²ΠΎΠΈΡ‡Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅
packages/result-app/public/logo192.png

Π”Π²ΠΎΠΈΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Π½Π΅ отобраТаСтся.

Π”ΠΎ

Π¨ΠΈΡ€ΠΈΠ½Π°:  |  Высота:  |  Π Π°Π·ΠΌΠ΅Ρ€: 5.2 KiB

Π”Π²ΠΎΠΈΡ‡Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅
packages/result-app/public/logo512.png

Π”Π²ΠΎΠΈΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Π½Π΅ отобраТаСтся.

Π”ΠΎ

Π¨ΠΈΡ€ΠΈΠ½Π°:  |  Высота:  |  Π Π°Π·ΠΌΠ΅Ρ€: 9.4 KiB

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,24 +0,0 @@
import React from 'react';
import { render } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { IntlProvider } from 'react-intl';
import { createTheme, CssBaseline, MuiThemeProvider } from '@material-ui/core';
import App from './App';
import en from './lang/en.json';
test('renders learn react link', () => {
const queryClient = new QueryClient();
render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<IntlProvider locale="en" messages={en}>
<MuiThemeProvider theme={createTheme()}>
<CssBaseline />
<App />
</MuiThemeProvider>
</IntlProvider>
</QueryClientProvider>
</React.StrictMode>
);
});

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,15 +0,0 @@
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { DefaultLayout } from './layouts';
import MainRoutes from './routes/MainRoutes';
const App: React.FunctionComponent = () => (
<Router>
<DefaultLayout>
<MainRoutes />
</DefaultLayout>
</Router>
);
export default App;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,63 +0,0 @@
import { Box, Button, AppBar as MaterialAppBar, Toolbar, makeStyles } from '@material-ui/core';
import React, { SVGProps, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { MessageId } from '../../lang';
export interface AppBarProps {
title?: string;
Logo?: React.ComponentType<SVGProps<SVGSVGElement>>;
loggedIn?: boolean;
}
const useStyles = makeStyles((theme) => ({
toolbar: {
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
},
logoContainer: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'flex-start',
flexGrow: 1,
},
logo: {
height: 24,
width: 150,
fill: theme.palette.getContrastText(theme.palette.primary.main),
[theme.breakpoints.up('sm')]: {
height: 30,
width: 190,
},
},
}));
/**
* A persistent top App Bar with side drawer and optional additional content.
*/
export const AppBar: React.FunctionComponent<AppBarProps> = ({ title, Logo, loggedIn = false }) => {
const [signedIn, setSignIn] = useState(loggedIn);
const classes = useStyles();
return (
<MaterialAppBar position="static" title={title}>
<Toolbar className={classes.toolbar}>
<Box className={classes.logoContainer}>
{Logo && <Logo className={classes.logo} />}
</Box>
{signedIn && (
<Button color="inherit" onClick={() => setSignIn(!signedIn)}>
<FormattedMessage
id={MessageId.AuthLogout}
description="Sign out of application"
defaultMessage="Sign Out"
/>
</Button>
)}
</Toolbar>
</MaterialAppBar>
);
};
export default AppBar;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,5 +0,0 @@
import AppBar from './AppBar';
export * from './AppBar';
export default AppBar;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,21 +0,0 @@
import { Box, makeStyles } from '@material-ui/core';
import React from 'react';
const useStyles = makeStyles((theme) => ({
root: {
background: theme.palette.grey[800],
height: theme.spacing(4),
flexShrink: 0,
},
}));
/**
* A persistent footer for additional content
*/
export const Footer: React.FunctionComponent = () => {
const classes = useStyles();
return <Box className={classes.root} />;
};
export default Footer;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,5 +0,0 @@
import Footer from './Footer';
export * from './Footer';
export default Footer;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,63 +0,0 @@
/* eslint-disable react/jsx-props-no-spreading */
import { Box, Typography, TypographyProps, useTheme } from '@material-ui/core';
import React from 'react';
import { useIntl } from 'react-intl';
import { GenericMessage } from '../../lang';
export interface InternationalTextProps extends TypographyProps {
id?: string;
description?: string;
defaultMessage?: string;
component?: React.ElementType;
screenReaderOnly?: boolean;
}
const bold = (str: string) => (
<Box fontWeight="fontWeightMedium" display="inline" component="b">
{str}
</Box>
);
const italic = (str: string) => (
<Box fontStyle="italics" display="inline" component="i">
{str}
</Box>
);
const colored = (str: string, color: string) => (
<Box color={color} fontWeight="fontWeightMedium" display="inline" component="b">
{str}
</Box>
);
/**
* International text to handle automatically finding correct language
*/
export const InternationalText: React.FC<InternationalTextProps> = (props) => {
const theme = useTheme();
const intl = useIntl();
const typographyProps = props as TypographyProps;
const { id, description, defaultMessage, component, screenReaderOnly } = props;
const message = intl.formatMessage(
new GenericMessage<string>(id, defaultMessage, description),
{
bold,
italic,
primary: (str: string) => colored(str, theme.palette.primary.main),
secondary: (str: string) => colored(str, theme.palette.secondary.main),
}
);
if (screenReaderOnly) {
return (
<Typography {...typographyProps} component={component || 'span'} aria-label={message} />
);
}
return (
<Typography {...typographyProps} component={component || 'span'}>
{message}
</Typography>
);
};
export default InternationalText;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,5 +0,0 @@
import InternationalText from './InternationalText';
export * from './InternationalText';
export default InternationalText;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,64 +0,0 @@
import { ButtonBase, Card, CardContent, SvgIconProps, makeStyles } from '@material-ui/core';
import React from 'react';
import { Message } from '../../lang';
import InternationalText from '../InternationalText';
const useStyles = makeStyles((theme) => ({
root: {
height: 144,
width: 144,
margin: theme.spacing(2),
},
clickable: {
width: '100%',
height: '100%',
paddingTop: theme.spacing(2),
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center',
},
content: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 14,
textAlign: 'center',
},
}));
export interface MenuOptionProps {
title: Message;
Icon: React.ComponentType<SvgIconProps>;
onClick?: () => void;
disabled?: boolean;
}
/**
* A menu option card for the menu screens
*/
export const MenuOption: React.FC<MenuOptionProps> = ({ title, Icon, disabled, onClick }) => {
const classes = useStyles();
return (
<Card elevation={10} className={classes.root}>
<ButtonBase className={classes.clickable} disabled={disabled} onClick={onClick}>
<CardContent className={classes.content}>
<Icon color="primary" fontSize="large" />
<InternationalText
className={classes.title}
color="textSecondary"
id={title.id}
defaultMessage={title.defaultMessage}
/>
</CardContent>
</ButtonBase>
</Card>
);
};
export default MenuOption;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,73 +0,0 @@
import { SvgIconProps } from '@material-ui/core';
import {
AccountCircleOutlined,
AddCircleOutlineOutlined,
BallotOutlined,
LibraryAddCheckOutlined,
PublishOutlined,
QuestionAnswer,
VpnKeyOutlined,
} from '@material-ui/icons';
import { Message, MessageId, OverloadMessageId } from '../../lang';
import { MenuOptionType } from './MenuOptionType';
export default interface MenuOptionPreset {
title: Message;
Icon: React.ComponentType<SvgIconProps>;
}
export const getPreset = (type: MenuOptionType): MenuOptionPreset => {
switch (type) {
case MenuOptionType.ManageUsers:
return {
title: new Message(MessageId.MenuOption_ManageUsers),
Icon: AccountCircleOutlined,
};
case MenuOptionType.BeginKeyCeremony:
return {
title: new Message(MessageId.MenuOption_JoinKeyCeremony),
Icon: VpnKeyOutlined,
};
case MenuOptionType.SetupElection:
return {
title: new Message(MessageId.MenuOption_SetupElection),
Icon: BallotOutlined,
};
case MenuOptionType.BeginTallyCeremony:
return {
title: new Message(MessageId.MenuOption_BeginTallyCeremony),
Icon: LibraryAddCheckOutlined,
};
case MenuOptionType.UploadManifest:
return {
title: new Message(MessageId.MenuOption_UploadManifest),
Icon: PublishOutlined,
};
case MenuOptionType.BuildManifest:
return {
title: new Message(MessageId.MenuOption_BuildManifest),
Icon: AddCircleOutlineOutlined,
};
case MenuOptionType.ManageJointKeys:
return {
title: new Message(MessageId.MenuOption_ManageJointKeys),
Icon: VpnKeyOutlined,
};
case MenuOptionType.ManageElections:
return {
title: new Message(MessageId.MenuOption_ManageElections),
Icon: BallotOutlined,
};
case MenuOptionType.SetupJointKeys:
return {
title: new Message(MessageId.MenuOption_SetupJointKey),
Icon: VpnKeyOutlined,
};
default:
return {
title: new Message(OverloadMessageId, 'Unknown'),
Icon: QuestionAnswer,
};
}
};

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,13 +0,0 @@
export enum MenuOptionType {
ManageUsers = 'manage-users',
BeginKeyCeremony = 'begin-key-ceremony',
SetupElection = 'setup-election',
BeginTallyCeremony = 'begin-tally-ceremony',
UploadManifest = 'upload-manifest',
BuildManifest = 'build-manifest',
ManageJointKeys = 'manage-joint-key',
ManageElections = 'manage-elections',
SetupJointKeys = 'setup-joint-key',
}
export default MenuOptionType;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,55 +0,0 @@
import { Box, Container, Grid, lighten, makeStyles } from '@material-ui/core';
import React from 'react';
import { Message } from '../../lang';
import InternationalText from '../InternationalText';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
background: lighten(theme.palette.primary.main, 0.9),
padding: theme.spacing(4),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
prompt: {
textAlign: 'center',
marginBottom: theme.spacing(2),
},
options: {
display: 'flex',
justifyContent: 'center',
},
}));
export interface MenuOptionsProps {
prompt: Message;
}
/**
* A set of menu options with a prompt
* TODO Deteremine options based on permissions
*/
export const MenuOptions: React.FC<MenuOptionsProps> = ({ prompt, children }) => {
const classes = useStyles();
return (
<Box className={classes.root}>
<InternationalText
variant="h5"
component="p"
className={classes.prompt}
id={prompt.id}
description="Prompt for a user on menu"
defaultMessage={prompt.defaultMessage}
/>
<Container maxWidth="xs">
<Grid container className={classes.options}>
{children}
</Grid>
</Container>
</Box>
);
};
export default MenuOptions;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,21 +0,0 @@
import React from 'react';
import MenuOption from './MenuOption';
import { getPreset } from './MenuOptionPreset';
import { MenuOptionType } from './MenuOptionType';
export interface TypedMenuOptionProps {
type: MenuOptionType;
onClick?: () => void;
disabled?: boolean;
}
/**
* A typed menu option card for the menu screens
*/
export const TypedMenuOption: React.FC<TypedMenuOptionProps> = ({ type, disabled, onClick }) => {
const { title, Icon } = getPreset(type);
return <MenuOption title={title} Icon={Icon} disabled={disabled} onClick={onClick} />;
};
export default TypedMenuOption;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,4 +0,0 @@
export * from './MenuOption';
export * from './MenuOptions';
export * from './MenuOptionType';
export * from './TypedMenuOption';

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,64 +0,0 @@
import { Grid, makeStyles } from '@material-ui/core';
import React, { SVGProps } from 'react';
import { MessageId } from '../../lang';
import InternationalText from '../InternationalText';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
color: theme.palette.grey[600],
fill: theme.palette.grey[600],
},
welcomeText: {
fontSize: '1.5rem',
[theme.breakpoints.up('sm')]: {
fontSize: '3rem',
},
},
logo: {
marginTop: -theme.spacing(2),
fill: 'inherit',
height: 45,
width: 250,
[theme.breakpoints.up('sm')]: {
height: 90,
width: 500,
},
},
}));
export interface WelcomeHeaderProps {
Logo?: React.ComponentType<SVGProps<SVGSVGElement>>;
}
/**
* A menu option card for the menu screens
*/
export const WelcomeHeader: React.FC<WelcomeHeaderProps> = ({ Logo }) => {
const classes = useStyles();
return (
<Grid container className={classes.root}>
<Grid item>
<InternationalText
variant="h3"
component="span"
className={classes.welcomeText}
id={MessageId.AppGreeting}
description="Greeting to welcome the user to the app"
defaultMessage="Welcome to"
/>
</Grid>
{Logo && (
<Grid item>
<Logo className={classes.logo} />
</Grid>
)}
</Grid>
);
};
export default WelcomeHeader;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,5 +0,0 @@
import WelcomeHeader from './WelcomeHeader';
export * from './WelcomeHeader';
export default WelcomeHeader;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,15 +0,0 @@
import React, { SVGProps } from 'react';
export interface Config {
appName: string;
logo?: React.ComponentType<SVGProps<SVGSVGElement>>;
}
export const defaultConfig: Config = {
appName: 'Unknown App',
logo: undefined,
};
export const ConfigContext = React.createContext(defaultConfig);
export default ConfigContext;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1 +0,0 @@
export * from './config';

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,90 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version="1.1"
id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
width="90px"
height="60"
viewBox="90 0 90 205.49"
enable-background="new 90 0 90 205.49"
xml:space="preserve"
role="img"
aria-labelledby="logoTitle logoDesc"
>
<title id="logoTitle">ElectionGuard Logo</title>
<desc id="logoDesc">The ElectionGuard logo</desc>
<g>
<g>
<g id="ElectionGuard_Icon_1">
<g>
<path
fill="#008575"
d="M50.38,102.676c0.654-2.725,1.679-3.67,4.542-3.604c8.801,0.203,17.609,0.073,26.6,0.073
c0,7.805,0,15.254,0,23.249c-1.839,0-3.598-0.029-5.364,0c-10.16,0.182-17.726,7.762-17.697,17.719
c0.022,9.462,7.667,17.108,17.486,17.115c42.61,0.072,85.221,0.072,127.838,0c9.957-0.021,17.457-7.776,17.377-17.566
c-0.073-9.666-7.828-17.195-17.762-17.261c-1.672,0-3.343,0-5.233,0c0-7.754,0-15.211,0-22.893
c0.545-0.109,1.221-0.349,1.89-0.349c8.474-0.021,16.948,0.007,25.422-0.043c1.751-0.015,2.9,0.218,3.401,2.231
c6.424,26.033,12.915,52.037,19.39,78.055c0.051,0.226-0.029,0.473-0.065,0.938c-72.19,0-144.394,0-217.078,0
c2.943-11.934,5.792-23.533,8.677-35.125C43.337,131.035,46.979,116.877,50.38,102.676z"
/>
<path
fill="#FFFFFF"
d="M186.024,145.468c-30.779,0-61.463,0-92.416,0c0-38.534,0-77.052,0-115.92c30.938,0,61.536,0,92.416,0
C186.024,68.198,186.024,106.717,186.024,145.468z"
/>
<path
fill="#274B47"
d="M186.024,29.548c-30.88,0-61.478,0-92.416,0c0,38.868,0,77.386,0,115.92c30.953,0,61.637,0,92.416,0
C186.024,106.717,186.024,68.198,186.024,29.548z M54.922,99.071c-2.864-0.065-3.888,0.879-4.542,3.604
c-3.401,14.201-7.042,28.359-10.575,42.538c-2.885,11.592-5.734,23.191-8.677,35.125c72.684,0,144.888,0,217.078,0
c0.036-0.465,0.116-0.712,0.065-0.938c-6.476-26.019-12.966-52.022-19.39-78.055c-0.501-2.013-1.65-2.246-3.401-2.231
c-8.474,0.051-16.948,0.022-25.422,0.043c-0.668,0-1.345,0.24-1.89,0.349c0,7.682,0,15.139,0,22.893c1.89,0,3.561,0,5.233,0
c9.935,0.065,17.689,7.595,17.762,17.261c0.08,9.79-7.42,17.545-17.377,17.566c-42.618,0.072-85.228,0.072-127.838,0
c-9.819-0.007-17.464-7.653-17.486-17.115c-0.029-9.957,7.537-17.537,17.697-17.719c1.766-0.029,3.525,0,5.364,0
c0-7.995,0-15.444,0-23.249C72.532,99.144,63.723,99.274,54.922,99.071z M25.757,192.163c-6.904,0-8.976-2.492-7.304-9.28
c6.606-26.738,13.321-53.439,20-80.156c0.785-3.161,1.577-6.323,2.376-9.491c1.076-4.245,2.784-5.662,7.123-5.676
c10.654-0.029,21.309-0.015,31.963-0.029c0.458,0,0.923-0.124,1.788-0.24c0-20.066,0-39.797,0-59.522
c0-0.974-0.015-1.94,0.007-2.907c0.08-5.095,1.955-7.028,7.064-7.035c19.128-0.036,38.264-0.029,57.393-0.029
c14.644,0,29.296-0.007,43.947,0.021c6.09,0.007,7.82,1.73,7.82,7.748c0.015,19.128,0.007,38.257,0.007,57.378
c0,1.33,0,2.66,0,4.571c1.453,0,2.725,0,3.997,0c9.928,0.015,19.855,0,29.783,0.043c4.201,0.022,6.054,1.403,7.035,5.334
c7.522,30.118,15.044,60.227,22.486,90.359c1.555,6.301-0.589,8.91-7.021,8.91c-54.239,0.021-108.478,0.021-162.723,0.021
C69.588,192.184,47.676,192.184,25.757,192.163z"
/>
</g>
<g />
</g>
</g>
<g>
<g id="ElectionGuard_Icon_2">
<g>
<path
fill="#FFFFFF"
d="M157.045,67.984c0.734-0.736,1.479-1.544,2.631-1.395c0.628,0.083,1.344,0.278,1.81,0.672
c1.28,1.074,2.478,2.248,3.65,3.44c1.418,1.443,1.327,3.301-0.194,4.83c-5.963,5.995-11.928,11.983-17.901,17.976
c-4.404,4.413-8.819,8.817-13.227,13.227c-1.766,1.768-3.53,1.76-5.301-0.009c-4.818-4.822-9.637-9.637-14.454-14.458
c-1.968-1.968-1.945-3.57,0.077-5.533c0.849-0.823,1.72-1.634,2.573-2.454c1.696-1.636,3.146-1.649,4.804,0
c2.953,2.941,5.891,5.894,8.821,8.857c0.234,0.232,0.363,0.566,0.692,1.086c0.443-0.593,0.63-0.92,0.883-1.172
C140.284,84.691,148.663,76.334,157.045,67.984z"
/>
<path
fill="#274B47"
d="M159.677,66.589c-1.152-0.149-1.897,0.659-2.631,1.395c-8.382,8.35-16.762,16.707-25.135,25.068
c-0.253,0.252-0.44,0.579-0.883,1.172c-0.329-0.52-0.458-0.854-0.692-1.086c-2.93-2.963-5.868-5.916-8.821-8.857
c-1.658-1.649-3.107-1.636-4.804,0c-0.853,0.82-1.724,1.63-2.573,2.454c-2.021,1.963-2.045,3.564-0.077,5.533
c4.816,4.82,9.635,9.635,14.454,14.458c1.771,1.769,3.535,1.776,5.301,0.009c4.408-4.409,8.823-8.813,13.227-13.227
c5.973-5.993,11.938-11.981,17.901-17.976c1.521-1.528,1.612-3.387,0.194-4.83c-1.172-1.192-2.37-2.366-3.65-3.44
C161.021,66.867,160.305,66.672,159.677,66.589z M139.3,125.711c-21.407-0.206-38.353-17.172-38.342-38.453
c0.013-21.349,17.136-38.424,38.49-38.362c21.323,0.062,38.34,17.102,38.287,38.47
C177.686,108.788,160.615,125.558,139.3,125.711z"
/>
</g>
<g />
</g>
</g>
</g>
</svg>

Π”ΠΎ

Π¨ΠΈΡ€ΠΈΠ½Π°:  |  Высота:  |  Π Π°Π·ΠΌΠ΅Ρ€: 5.4 KiB

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,178 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version="1.1"
id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
width="1246.438px"
height="205.49px"
viewBox="0 0 1246.438 205.49"
enable-background="new 0 0 1246.438 205.49"
xml:space="preserve"
role="img"
aria-labelledby="bannerTitle bannerDesc"
>
<title id="bannerTitle">ElectionGuard Banner</title>
<desc id="bannerDesc">The ElectionGuard logo in banner format</desc>
<g>
<g>
<g id="ElectionGuard_Icon_1">
<g>
<path
fill="#008575"
d="M50.38,102.676c0.654-2.725,1.679-3.67,4.542-3.604c8.801,0.203,17.609,0.073,26.6,0.073
c0,7.805,0,15.254,0,23.249c-1.839,0-3.598-0.029-5.364,0c-10.16,0.182-17.726,7.762-17.697,17.719
c0.022,9.462,7.667,17.108,17.486,17.115c42.61,0.072,85.221,0.072,127.838,0c9.957-0.021,17.457-7.776,17.377-17.566
c-0.073-9.666-7.828-17.195-17.762-17.261c-1.672,0-3.343,0-5.233,0c0-7.754,0-15.211,0-22.893
c0.545-0.109,1.221-0.349,1.89-0.349c8.474-0.021,16.948,0.007,25.422-0.043c1.751-0.015,2.9,0.218,3.401,2.231
c6.424,26.033,12.915,52.037,19.39,78.055c0.051,0.226-0.029,0.473-0.065,0.938c-72.19,0-144.394,0-217.078,0
c2.943-11.934,5.792-23.533,8.677-35.125C43.337,131.035,46.979,116.877,50.38,102.676z"
/>
<path
fill="#FFFFFF"
d="M186.024,145.468c-30.779,0-61.463,0-92.416,0c0-38.534,0-77.052,0-115.92c30.938,0,61.536,0,92.416,0
C186.024,68.198,186.024,106.717,186.024,145.468z"
/>
<path
fill="#274B47"
d="M186.024,29.548c-30.88,0-61.478,0-92.416,0c0,38.868,0,77.386,0,115.92c30.953,0,61.637,0,92.416,0
C186.024,106.717,186.024,68.198,186.024,29.548z M54.922,99.071c-2.864-0.065-3.888,0.879-4.542,3.604
c-3.401,14.201-7.042,28.359-10.575,42.538c-2.885,11.592-5.734,23.191-8.677,35.125c72.684,0,144.888,0,217.078,0
c0.036-0.465,0.116-0.712,0.065-0.938c-6.476-26.019-12.966-52.022-19.39-78.055c-0.501-2.013-1.65-2.246-3.401-2.231
c-8.474,0.051-16.948,0.022-25.422,0.043c-0.668,0-1.345,0.24-1.89,0.349c0,7.682,0,15.139,0,22.893c1.89,0,3.561,0,5.233,0
c9.935,0.065,17.689,7.595,17.762,17.261c0.08,9.79-7.42,17.545-17.377,17.566c-42.618,0.072-85.228,0.072-127.838,0
c-9.819-0.007-17.464-7.653-17.486-17.115c-0.029-9.957,7.537-17.537,17.697-17.719c1.766-0.029,3.525,0,5.364,0
c0-7.995,0-15.444,0-23.249C72.532,99.144,63.723,99.274,54.922,99.071z M25.757,192.163c-6.904,0-8.976-2.492-7.304-9.28
c6.606-26.738,13.321-53.439,20-80.156c0.785-3.161,1.577-6.323,2.376-9.491c1.076-4.245,2.784-5.662,7.123-5.676
c10.654-0.029,21.309-0.015,31.963-0.029c0.458,0,0.923-0.124,1.788-0.24c0-20.066,0-39.797,0-59.522
c0-0.974-0.015-1.94,0.007-2.907c0.08-5.095,1.955-7.028,7.064-7.035c19.128-0.036,38.264-0.029,57.393-0.029
c14.644,0,29.296-0.007,43.947,0.021c6.09,0.007,7.82,1.73,7.82,7.748c0.015,19.128,0.007,38.257,0.007,57.378
c0,1.33,0,2.66,0,4.571c1.453,0,2.725,0,3.997,0c9.928,0.015,19.855,0,29.783,0.043c4.201,0.022,6.054,1.403,7.035,5.334
c7.522,30.118,15.044,60.227,22.486,90.359c1.555,6.301-0.589,8.91-7.021,8.91c-54.239,0.021-108.478,0.021-162.723,0.021
C69.588,192.184,47.676,192.184,25.757,192.163z"
/>
</g>
<g />
</g>
</g>
<g>
<g id="ElectionGuard_Icon_2">
<g>
<path
fill="#FFFFFF"
d="M157.045,67.984c0.734-0.736,1.479-1.544,2.631-1.395c0.628,0.083,1.344,0.278,1.81,0.672
c1.28,1.074,2.478,2.248,3.65,3.44c1.418,1.443,1.327,3.301-0.194,4.83c-5.963,5.995-11.928,11.983-17.901,17.976
c-4.404,4.413-8.819,8.817-13.227,13.227c-1.766,1.768-3.53,1.76-5.301-0.009c-4.818-4.822-9.637-9.637-14.454-14.458
c-1.968-1.968-1.945-3.57,0.077-5.533c0.849-0.823,1.72-1.634,2.573-2.454c1.696-1.636,3.146-1.649,4.804,0
c2.953,2.941,5.891,5.894,8.821,8.857c0.234,0.232,0.363,0.566,0.692,1.086c0.443-0.593,0.63-0.92,0.883-1.172
C140.284,84.691,148.663,76.334,157.045,67.984z"
/>
<path
fill="#274B47"
d="M159.677,66.589c-1.152-0.149-1.897,0.659-2.631,1.395c-8.382,8.35-16.762,16.707-25.135,25.068
c-0.253,0.252-0.44,0.579-0.883,1.172c-0.329-0.52-0.458-0.854-0.692-1.086c-2.93-2.963-5.868-5.916-8.821-8.857
c-1.658-1.649-3.107-1.636-4.804,0c-0.853,0.82-1.724,1.63-2.573,2.454c-2.021,1.963-2.045,3.564-0.077,5.533
c4.816,4.82,9.635,9.635,14.454,14.458c1.771,1.769,3.535,1.776,5.301,0.009c4.408-4.409,8.823-8.813,13.227-13.227
c5.973-5.993,11.938-11.981,17.901-17.976c1.521-1.528,1.612-3.387,0.194-4.83c-1.172-1.192-2.37-2.366-3.65-3.44
C161.021,66.867,160.305,66.672,159.677,66.589z M139.3,125.711c-21.407-0.206-38.353-17.172-38.342-38.453
c0.013-21.349,17.136-38.424,38.49-38.362c21.323,0.062,38.34,17.102,38.287,38.47
C177.686,108.788,160.615,125.558,139.3,125.711z"
/>
</g>
<g />
</g>
</g>
</g>
<path
fill="current"
d="M385.763,157.191H329.43V56.843h54.093v14.135h-37.438V99.39h34.498v14.063h-34.498v29.672h39.678V157.191z"
/>
<path fill="current" d="M418.092,157.191h-16.303V51.105h16.303V157.191z" />
<path
fill="current"
d="M499.897,125.774h-48.844c0.185,6.622,2.227,11.73,6.122,15.322c3.896,3.595,9.25,5.39,16.062,5.39
c7.649,0,14.671-2.286,21.062-6.857v13.083c-6.531,4.106-15.162,6.158-25.891,6.158c-10.543,0-18.814-3.252-24.808-9.761
c-5.995-6.509-8.992-15.663-8.992-27.469c0-11.147,3.299-20.231,9.901-27.253c6.602-7.023,14.801-10.534,24.598-10.534
c9.796,0,17.376,3.149,22.742,9.447c5.365,6.301,8.047,15.047,8.047,26.243V125.774z M484.222,114.294
c-0.047-5.829-1.423-10.368-4.129-13.609c-2.706-3.244-6.438-4.865-11.196-4.865c-4.666,0-8.619,1.703-11.862,5.108
c-3.241,3.403-5.235,7.861-5.981,13.366H484.222z"
/>
<path
fill="current"
d="M566.657,153.904c-5.738,3.309-12.525,4.966-20.363,4.966c-10.637,0-19.221-3.322-25.752-9.972
c-6.532-6.646-9.798-15.266-9.798-25.857c0-11.801,3.511-21.283,10.532-28.445c7.021-7.159,16.411-10.742,28.166-10.742
c6.53,0,12.292,1.144,17.285,3.43v15.117c-4.993-3.734-10.311-5.597-15.955-5.597c-6.858,0-12.479,2.318-16.864,6.96
c-4.387,4.642-6.579,10.721-6.579,18.231c0,7.418,2.064,13.271,6.193,17.563c4.128,4.293,9.668,6.44,16.619,6.44
c5.831,0,11.336-2.077,16.516-6.23V153.904z"
/>
<path
fill="current"
d="M620.539,156.423c-3.173,1.583-7.347,2.376-12.524,2.376c-13.904,0-20.854-6.669-20.854-20.013V98.271
h-11.966V85.534h11.966V68.949l16.234-4.62v21.205h17.144v12.737h-17.144v35.827c0,4.247,0.771,7.277,2.31,9.099
c1.539,1.819,4.105,2.729,7.698,2.729c2.752,0,5.13-0.793,7.137-2.378V156.423z"
/>
<path
fill="current"
d="M642.723,70.487c-2.66,0-4.935-0.859-6.824-2.588c-1.889-1.725-2.831-3.916-2.831-6.579
c0-2.658,0.942-4.876,2.831-6.646c1.889-1.771,4.164-2.658,6.824-2.658c2.753,0,5.084,0.887,6.998,2.658
c1.913,1.771,2.869,3.988,2.869,6.646c0,2.518-0.956,4.679-2.869,6.476C647.808,69.59,645.476,70.487,642.723,70.487z
M650.771,157.191h-16.235V85.534h16.235V157.191z"
/>
<path
fill="current"
d="M703.743,158.87c-11.056,0-19.885-3.347-26.486-10.042c-6.601-6.692-9.901-15.568-9.901-26.626
c0-12.036,3.441-21.433,10.322-28.2c6.881-6.763,16.153-10.148,27.816-10.148c11.196,0,19.918,3.289,26.171,9.868
c6.252,6.579,9.377,15.7,9.377,27.358c0,11.436-3.371,20.587-10.112,27.468C724.189,155.429,715.125,158.87,703.743,158.87z
M704.514,96.802c-6.347,0-11.36,2.213-15.044,6.645c-3.688,4.434-5.529,10.545-5.529,18.336c0,7.511,1.865,13.423,5.599,17.74
c3.732,4.315,8.722,6.474,14.974,6.474c6.391,0,11.302-2.124,14.731-6.368c3.427-4.247,5.141-10.291,5.141-18.124
c0-7.885-1.714-13.973-5.141-18.266C715.816,98.946,710.905,96.802,704.514,96.802z"
/>
<path
fill="current"
d="M821.377,157.191h-16.235v-40.376c0-13.39-4.733-20.083-14.205-20.083c-4.944,0-9.029,1.852-12.246,5.562
c-3.219,3.708-4.83,8.385-4.83,14.03v40.867h-16.305V85.534h16.305v11.896h0.28c5.365-9.051,13.109-13.576,23.232-13.576
c7.793,0,13.738,2.535,17.847,7.593c4.105,5.062,6.156,12.375,6.156,21.937V157.191z"
/>
<path
fill="current"
d="M921.307,150.332c-10.451,5.693-22.092,8.538-34.917,8.538c-14.836,0-26.85-4.615-36.041-13.854
s-13.785-21.459-13.785-36.668c0-15.538,5.025-28.283,15.078-38.242c10.055-9.962,22.824-14.941,38.314-14.941
c11.15,0,20.527,1.633,28.132,4.896v17.146c-7.696-5.132-16.863-7.699-27.501-7.699c-10.684,0-19.443,3.526-26.278,10.565
c-6.835,7.047-10.249,16.168-10.249,27.362c0,11.523,2.937,20.587,8.816,27.188c5.877,6.604,13.857,9.901,23.933,9.901
c6.903,0,12.875-1.328,17.916-3.988v-23.861h-21.135V102.68h37.718V150.332z"
/>
<path
fill="current"
d="M1003.601,157.191h-16.236v-11.339h-0.278c-4.712,8.683-12.038,13.018-21.972,13.018
c-16.938,0-25.406-10.169-25.406-30.508V85.534h16.236v41.147c0,12.875,4.969,19.315,14.904,19.315c4.807,0,8.76-1.775,11.865-5.321
c3.101-3.545,4.65-8.187,4.65-13.924V85.534h16.236V157.191z"
/>
<path
fill="current"
d="M1079.736,157.191h-15.744v-11.194h-0.28c-4.946,8.582-12.2,12.873-21.762,12.873
c-7.048,0-12.562-1.911-16.55-5.737s-5.982-8.889-5.982-15.185c0-13.528,7.788-21.414,23.372-23.653l21.272-3.009
c0-10.219-4.853-15.325-14.556-15.325c-8.536,0-16.234,2.939-23.094,8.819V90.572c7.559-4.477,16.282-6.719,26.173-6.719
c18.102,0,27.15,8.913,27.15,26.733V157.191z M1064.062,121.994l-15.047,2.097c-4.663,0.609-8.174,1.74-10.53,3.393
c-2.357,1.659-3.534,4.563-3.534,8.714c0,3.032,1.085,5.518,3.254,7.455c2.172,1.933,5.073,2.901,8.711,2.901
c4.946,0,9.04-1.735,12.281-5.211c3.243-3.476,4.865-7.851,4.865-13.123V121.994z"
/>
<path
fill="current"
d="M1141.11,101.001c-1.961-1.542-4.784-2.314-8.472-2.314c-4.804,0-8.814,2.172-12.031,6.509
c-3.222,4.339-4.83,10.243-4.83,17.707v34.288h-16.235V85.534h16.235V100.3h0.278c1.584-5.041,4.025-8.97,7.313-11.792
c3.292-2.82,6.963-4.231,11.023-4.231c2.938,0,5.176,0.442,6.719,1.328V101.001z"
/>
<path
fill="current"
d="M1216.475,157.191h-16.234v-12.176h-0.28c-5.228,9.239-13.272,13.854-24.144,13.854
c-8.816,0-15.873-3.204-21.168-9.621c-5.295-6.414-7.941-15.151-7.941-26.208c0-11.849,2.928-21.343,8.783-28.478
c5.852-7.14,13.655-10.709,23.405-10.709c9.655,0,16.679,3.874,21.064,11.617h0.28V51.105h16.234V157.191z M1200.451,124.441v-9.375
c0-5.088-1.656-9.401-4.97-12.947s-7.534-5.316-12.665-5.316c-6.065,0-10.837,2.262-14.311,6.785
c-3.478,4.526-5.213,10.802-5.213,18.825c0,7.278,1.667,13.026,5.001,17.252c3.338,4.221,7.828,6.333,13.473,6.333
c5.552,0,10.053-2.042,13.504-6.123C1198.722,135.789,1200.451,130.648,1200.451,124.441z"
/>
</svg>

Π”ΠΎ

Π¨ΠΈΡ€ΠΈΠ½Π°:  |  Высота:  |  Π Π°Π·ΠΌΠ΅Ρ€: 11 KiB

10
packages/result-app/src/images/images.d.ts поставляСмый
ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,10 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module '*.svg' {
const content: any;
export default content;
}
declare module '*.png' {
const content: any;
export default content;
}

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,30 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { IntlProvider } from 'react-intl';
import { QueryClient, QueryClientProvider } from 'react-query';
import { CssBaseline, MuiThemeProvider, createTheme } from '@material-ui/core';
import App from './App';
import reportWebVitals from './reportWebVitals';
import en from './lang/en.json';
const queryClient = new QueryClient();
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<IntlProvider locale="en" messages={en}>
<MuiThemeProvider theme={createTheme()}>
<CssBaseline />
<App />
</MuiThemeProvider>
</IntlProvider>
</QueryClientProvider>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,27 +0,0 @@
import { MessageDescriptor } from '@formatjs/intl';
export const OverloadMessageId = 'overload';
const PlaceHolderMessageId = 'placeholder';
const placeholderMessage = 'Message Not Found';
export class GenericMessage<T extends string> implements MessageDescriptor {
id: T | typeof OverloadMessageId | typeof PlaceHolderMessageId;
defaultMessage: string;
description?: string;
constructor(
id: T | typeof OverloadMessageId | typeof PlaceHolderMessageId = PlaceHolderMessageId,
defaultMessage = placeholderMessage,
description?: string
) {
this.id = id;
this.defaultMessage = defaultMessage;
this.description = description;
}
}
export default GenericMessage;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,48 +0,0 @@
import { enUS, Localization } from '@material-ui/core/locale';
import { EnumDictionary } from '../utils/EnumDictionary';
import Locale from './Locale';
export interface Language {
name: string;
locale: Locale;
messages: { [key: string]: string };
mui: Localization;
}
/**
* Get language for locale based on list of supported languages
* @param languages
* @returns Language
*/
export const getLanguage = (languages: EnumDictionary<Locale, Language>): Language => {
const locale = navigator.language;
if (locale in Locale) {
return languages[locale as Locale];
}
return languages.en;
};
/**
* Get a dictionary of languages mapped to locales
* @param messages
* @returns Dictionary of Languages
*/
export const setupLanguages = (
messages: EnumDictionary<Locale, { [key: string]: string }>
): EnumDictionary<Locale, Language> => {
const english = {
name: 'English',
locale: Locale.English,
messages: messages[Locale.English] || {},
mui: enUS,
};
return {
[Locale.English]: english,
};
};
export default Language;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,5 +0,0 @@
export enum Locale {
English = 'en',
}
export default Locale;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,7 +0,0 @@
// TODO Remove after migration to Admin App
import GenericMessage from './GenericMessage';
import MessageId from './MessageId';
export class Message extends GenericMessage<MessageId> {}
export default Message;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,246 +0,0 @@
// TODO Remove after migration to Admin App
enum MessageId {
// App
AppName = 'app.name',
Placeholder = 'app.placeholder',
AppGreeting = 'app.greeting',
AppAbout = 'app.about',
// Auth
AuthLogout = 'auth.logout',
// Menu
MenuPrompt = 'menu.prompt',
MenuOption_ManageUsers = 'menu.option.manage_users',
MenuOption_JoinKeyCeremony = 'menu.option.join_key_ceremony',
MenuOption_SetupElection = 'menu.option.setup_election',
MenuOption_BeginTallyCeremony = 'menu.option.begin_tally_ceremony',
MenuOption_UploadManifest = 'menu.option.upload_manifest',
MenuOption_BuildManifest = 'menu.option.build_manifest',
MenuOption_ManageJointKeys = 'menu.option.manage_joint_keys',
MenuOption_ManageElections = 'menu.option.manage_elections',
MenuOption_SetupJointKey = 'menu.option.setup_joint_keys',
// Login Form
LoginFormUsername = 'login_form.username',
LoginFormPassword = 'login_form.password',
LoginFormSubmit = 'login_form.submit',
// Election Setup
ElectionSetupManifestMenuTitle = 'election_setup.manifest_menu.title',
ElectionSetupManifestMenuAbout = 'election_setup.manifest_menu.about',
ElectionSetupManifestMenuPrompt = 'election_setup.manifest_menu.prompt',
ElectionSetupJointKeyRetrievedTitle = 'election_setup.joint_key_retrieved.title',
ElectionSetupJointKeyRetrievedCTA = 'election_setup.joint_key_retrieved.cta',
ElectionSetupJointKeyRetrievedDescription = 'election_setup.joint_key_retrieved.description',
ElectionSetupJointKeyRetreivedNext = 'election_setup.joint_key_retrieved.next',
ElectionSetupJointKeySelectTitle = 'election_setup.joint_key_select.title',
ElectionSetupJointKeySelectDescription = 'election_setup.joint_key_select.description',
ElectionSetupJointKeySelectPrompt = 'election_setup.joint_key_select.prompt',
ElectionSetupJointKeySelectNext = 'election_setup.joint_key_select.next',
ElectionSetupManifestPreviewTitle = 'election_setup.manifest_preview.title',
ElectionSetupManifestPreviewPropertyName = 'election_setup.manifest_preview.property.name',
ElectionSetupManifestPreviewPropertyNumberOfContests = 'election_setup.manifest_preview.property.number_of_contests',
ElectionSetupManifestPreviewPropertyNumberOfStyles = 'election_setup.manifest_preview.property.numberOfStyles',
ElectionSetupManifestPreviewPropertyStartDate = 'election_setup.manifest_preview.property.start_date',
ElectionSetupManifestPreviewPropertyEndDate = 'election_setup.manifest_preview.property.end_date',
ElectionSetupManifestPreviewPropertyFileHash = 'election_setup.manifest_preview.property.file_hash',
ElectionSetupManifestPreviewPropertyFileName = 'election_setup.manifest_preview.property.file_name',
ElectionSetupManifestPreviewCaption = 'election_setup.manifest_preview.caption',
ElectionSetupManifestPreviewNext = 'election_setup.manifest_preview.next',
ElectionSetupManifestPreviewBackToMenu = 'election_setup.manifest_preview.back_to_menu',
ElectionSetupSetupCompleteTitle = 'election_setup.setup_complete.title',
ElectionSetupSetupCompleteNext = 'election_setup.setup_complete.next',
ElectionSetupUploadManifestTitle = 'election_setup.upload_manifest.title',
ElectionSetupUploadManifestUpload = 'election_setup.upload_manifest.upload',
ElectionSetupUploadManifestError = 'election_setup.upload_manifest.error',
// Election List
ElectionListTitle = 'election_list.title',
ElectionListDescription = 'election_list.description',
ElectionListGoHome = 'election_list.go_home',
// Joint Key Setup
JointKeySetup_KeySetup_Title = 'joint_key_setup.key_setup.title',
JointKeySetup_KeySetup_Description = 'joint_key_setup.key_setup.description',
JointKeySetup_KeySetup_KeyHeading = 'joint_key_setup.key_setup.key_heading',
JointKeySetup_KeySetup_NumberOfGuardiansHeading = 'joint_key_setup.key_setup.number_of_guardians_heading',
JointKeySetup_KeySetup_NumberOfGuardiansEmphasis = 'joint_key_setup.key_setup.number_of_guardians_emphasis',
JointKeySetup_KeySetup_NumberOfGuardiansDescription = 'joint_key_setup.key_setup.number_of_guardians_description',
JointKeySetup_KeySetup_QuorumHeading = 'joint_key_setup.key_setup.quorum_heading',
JointKeySetup_KeySetup_QuorumEmphasis = 'joint_key_setup.key_setup.quorum_emphasis',
JointKeySetup_KeySetup_QuorumDescription = 'joint_key_setup.key_setup.quorum_description',
JointKeySetup_KeySetupReview_Title = 'joint_key_setup.key_setup_review.title',
JointKeySetup_GuardianAssignment_Title = 'joint_key_setup.guardian_assignment.title',
JointKeySetup_GuardianAssignment_Description = 'joint_key_setup.guardian_assignment.description',
JointKeySetup_GuardianAssignment_AssignedLabel = 'joint_key_setup.guardian_assignment.assigned_label',
JointKeySetup_GuardianAssignment_NoGuardians = 'joint_key_setup.guardian_assignment.no_guardians',
JointKeySetup_GuardianAssignment_Assign = 'joint_key_setup.guardian_assignment.assign',
JointKeySetup_GuardianAssignmentReview_Title = 'joint_key_setup.guardian_assignment_review.title',
JointKeySetup_GuardianAssignmentReview_Description = 'joint_key_setup.guardian_assignment_review.description',
JointKeySetup_GuardianAssignmentReview_ConfirmationCallout = 'joint_key_setup.guardian_assignment_review.confirmation_callout',
JointKeySetup_GuardianAssignmentReview_Confirmation = 'joint_key_setup.guardian_assignment_review.confirmation',
KeyCeremonyList_Title = 'key_ceremony_list.title',
KeyCeremonyList_Description = 'key_ceremony_list.description',
JointKeyList_Title = 'joint_key_list.title',
JointKeyList_Description = 'joint_key_list.description',
// Key Ceremony
KeyCeremony_Introduction_Title = 'key_ceremony.introduction.title',
KeyCeremony_Introduction_Description = 'key_ceremony.introduction.description',
KeyCeremony_Introduction_StepsHeading = 'key_ceremony.introduction.steps_heading',
KeyCeremony_Introduction_StepsDescription = 'key_ceremony.introduction.steps_description',
KeyCeremony_Introduction_Step1 = 'key_ceremony.introduction.step1',
KeyCeremony_Introduction_Step2 = 'key_ceremony.introduction.step2',
KeyCeremony_Introduction_Step3 = 'key_ceremony.introduction.step3',
KeyCeremony_Introduction_Step4 = 'key_ceremony.introduction.step4',
KeyCeremony_Introduction_Step5 = 'key_ceremony.introduction.step5',
KeyCeremony_Introduction_Step6 = 'key_ceremony.introduction.step6',
KeyCeremony_Introduction_Step7 = 'key_ceremony.introduction.step7',
KeyCeremony_MeetGuardians_Title = 'key_ceremony.meet_guardians.title',
KeyCeremony_MeetGuardians_Description = 'key_ceremony.meet_guardians.description',
KeyCeremony_MeetGuardians_GuardianHeading = 'key_ceremony.meet_guardians.guardian_heading',
KeyCeremony_MeetGuardians_Button = 'key_ceremony.meet_guardians.button',
KeyCeremony_CreateKeyPair_Title = 'key_ceremony.create_keypair.title',
KeyCeremony_CreateKeyPair_Description = 'key_ceremony.create_keypair.description',
KeyCeremony_CreateKeyPair_Button = 'key_ceremony.create_keypair.button',
KeyCeremony_SharePublicKey_Title = 'key_ceremony.share_public_key.title',
KeyCeremony_SharePublicKey_Description = 'key_ceremony.share_public_key.description',
KeyCeremony_SharePublicKey_Button = 'key_ceremony.share_public_key.button',
KeyCeremony_CreateBackups_Title = 'key_ceremony.create_backups.title',
KeyCeremony_CreateBackups_Description = 'key_ceremony.create_backups.description',
KeyCeremony_CreateBackups_Button = 'key_ceremony.create_backups.button',
KeyCeremony_CreateBackups_DisabledButton = 'key_ceremony.create_backups.disabled_button',
KeyCeremony_ShareBackups_Title = 'key_ceremony.share_backups.title',
KeyCeremony_ShareBackups_Description = 'key_ceremony.share_backups.description',
KeyCeremony_ShareBackups_Button = 'key_ceremony.share_backups.button',
KeyCeremony_VerifyBackups_Title = 'key_ceremony.verify_backups.title',
KeyCeremony_VerifyBackups_Description = 'key_ceremony.verify_backups.description',
KeyCeremony_VerifyBackups_Button = 'key_ceremony.verify_backups.button',
KeyCeremony_CombineKeys_Title = 'key_ceremony.combine_keys.title',
KeyCeremony_CombineKeys_Description = 'key_ceremony.combine_keys.description',
KeyCeremony_CombineKeys_Button = 'key_ceremony.combine_keys.button',
KeyCeremony_CombineKeys_DisabledButton = 'key_ceremony.combine_keys.disabled_button',
KeyCeremony_Complete_Title = 'key_ceremony.complete.title',
KeyCeremony_Complete_Description = 'key_ceremony.complete.description',
KeyCeremony_Complete_Button = 'key_ceremony.complete.button',
KeyCeremony_Vizualization_Complete = 'key_ceremony.visualization_complete',
KeyCeremony_Steps_Instructions = 'key_ceremony.steps.instructions',
KeyCeremony_Steps_MeetGuardians = 'key_ceremony.steps.meet_guardians',
KeyCeremony_Steps_CreateKeypair = 'key_ceremony.steps.create_keypair',
KeyCeremony_Steps_SharePublicKey = 'key_ceremony.steps.share_public_key',
KeyCeremony_Steps_CreateBackups = 'key_ceremony.steps.create_backups',
KeyCeremony_Steps_ShareBackups = 'key_ceremony.steps.share_backups',
KeyCeremony_Steps_VerifyBackups = 'key_ceremony.steps.verify_backups',
KeyCeremony_Steps_CombineKeys = 'key_ceremony.steps.combine_keys',
KeyCeremony_Steps_Complete = 'key_ceremony.steps.complete',
// Tally Ceremony
// -- Steps
TallyCeremony_Introduction_Title = 'tally_ceremony.introduction.title',
TallyCeremony_Introduction_Description = 'tally_ceremony.introduction.description',
TallyCeremony_Introduction_Button = 'tally_ceremony.introduction.button',
TallyCeremony_Introduction_StepsHeading = 'tally_ceremony.introduction.steps_heading',
TallyCeremony_Introduction_StepsDescription = 'tally_ceremony.introduction.steps_description',
TallyCeremony_Introduction_Step1 = 'tally_ceremony.introduction.step1',
TallyCeremony_Introduction_Step2 = 'tally_ceremony.introduction.step2',
TallyCeremony_Introduction_Step3 = 'tally_ceremony.introduction.step3',
TallyCeremony_Introduction_Step4 = 'tally_ceremony.introduction.step4',
TallyCeremony_DownloadTally_Title = 'tally_ceremony.download_tally.title',
TallyCeremony_DownloadTally_Description = 'tally_ceremony.download_tally.description',
TallyCeremony_DownloadTally_Button = 'tally_ceremony.download_tally.button',
TallyCeremony_DecryptTallyShare_Title = 'tally_ceremony.decrypt_tally_share.title',
TallyCeremony_DecryptTallyShare_Description = 'tally_ceremony.decrypt_tally_share.description',
TallyCeremony_DecryptTallyShare_Button = 'tally_ceremony.decrypt_tally_share.button',
TallyCeremony_DecryptTallyShare_Decrypting = 'tally_ceremony.decrypt_tally_share.decrypting',
TallyCeremony_DecryptTallyShare_Complete = 'tally_ceremony.decrypt_tally_share.complete',
TallyCeremony_DecryptTallyShare_CompleteButton = 'tally_ceremony.decrypt_tally_share.complete_button',
TallyCeremony_UploadTallyShare_Title = 'tally_ceremony.upload_tally_share.title',
TallyCeremony_UploadTallyShare_Description = 'tally_ceremony.upload_tally_share.description',
TallyCeremony_UploadTallyShare_Button = 'tally_ceremony.upload_tally_share.button',
TallyCeremony_DecryptMissing_Title = 'tally_ceremony.decrypt_missing.title',
TallyCeremony_DecryptMissing_Description = 'tally_ceremony.decrypt_missing.description',
TallyCeremony_DecryptMissing_Button = 'tally_ceremony.decrypt_missing.button',
TallyCeremony_DecryptMissing_Decrypting = 'tally_ceremony.decrypt_missing.decrypting',
TallyCeremony_DecryptMissing_Complete = 'tally_ceremony.decrypt_missing.complete',
TallyCeremony_DecryptMissing_CompleteButton = 'tally_ceremony.decrypt_missing.complete_button',
TallyCeremony_NoMissing_Title = 'tally_ceremony.no_missing.title',
TallyCeremony_NoMissing_Description = 'tally_ceremony.no_missing.description',
TallyCeremony_NoMissing_Button = 'tally_ceremony.no_missing.button',
TallyCeremony_UploadMissing_Title = 'tally_ceremony.upload_missing.title',
TallyCeremony_UploadMissing_Description = 'tally_ceremony.upload_missing.description',
TallyCeremony_UploadMissing_Button = 'tally_ceremony.upload_missing.button',
TallyCeremony_CombineShares_Title = 'tally_ceremony.combine_shares.title',
TallyCeremony_CombineShares_Description = 'tally_ceremony.combine_shares.description',
TallyCeremony_CombineShares_Button = 'tally_ceremony.combine_shares.button',
TallyCeremony_CombineShares_ButtonDisabled = 'tally_ceremony.combine_shares.button_disabled',
TallyCeremony_Complete_Title = 'tally_ceremony.complete.title',
TallyCeremony_Complete_Description = 'tally_ceremony.complete.description',
TallyCeremony_Complete_Button = 'tally_ceremony.complete.button',
// -- Step Descriptions
TallyCeremony_Steps_Introduction = 'tally_ceremony.steps.introduction',
TallyCeremony_Steps_DownloadTally = 'tally_ceremony.steps.download_tally',
TallyCeremony_Steps_DecryptTallyShare = 'tally_ceremony.steps.decrypt_tally_share',
TallyCeremony_Steps_UploadTallyShare = 'tally_ceremony.steps.upload_tally_share',
TallyCeremony_Steps_DecryptMissing = 'tally_ceremony.steps.decrypt_missing',
TallyCeremony_Steps_UploadMissing = 'tally_ceremony.steps.upload_missing',
TallyCeremony_Steps_CombineShares = 'tally_ceremony.steps.combine_shares',
TallyCeremony_Steps_TallyComplete = 'tally_ceremony.steps.tally_complete',
// Models
JointKey_Name = 'joint_key.name',
JointKey_NumberOfGuardians = 'joint_key.number_of_guardians',
JointKey_Quorum = 'joint_key.quorum',
Guardian = 'guardian',
Guardian_Name = 'guardian.name',
// Placeholder
Placeholder_Processing = 'placeholder.processing',
Placeholder_Complete = 'placeholder.complete',
Placeholder_Error = 'placeholder.error',
// Actions
Actions_Cancel = 'actions.cancel',
Actions_Submit = 'actions.submit',
Actions_Confirm = 'actions.confirm',
Actions_Next = 'actions.next',
Actions_Back = 'actions.back',
Actions_Continue = 'actions.continue',
Actions_Previous = 'actions.previous',
Actions_Edit = 'actions.edit',
Nav_Return_Home = 'nav.return_home',
TaskStatus_Error = 'task_status.error',
TaskStatus_Complete = 'task_status.complete',
TaskStatus_Incomplete = 'task_status.incomplete',
}
export default MessageId;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,241 +0,0 @@
{
"app.name": "ElectionGuard",
"app.placeholder": "placeholder",
"app.greeting": "Welcome to",
"app.about": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"auth.logout": "Sign Out",
"menu.prompt": "What do you want to do?",
"menu.option.manage_users": "Manage Users",
"menu.option.join_key_ceremony": "Join Key Ceremony",
"menu.option.setup_election": "Setup Election",
"menu.option.begin_tally_ceremony": "Begin Tally Ceremony",
"menu.option.upload_manifest": "Upload Manifest",
"menu.option.build_manifest": "Build Manifest",
"menu.option.manage_joint_keys": "Manage Joint Keys",
"menu.option.manage_elections": "Manage Elections",
"menu.option.setup_joint_keys": "Setup Joint Keys",
"login_form.username": "Username",
"login_form.password": "Password",
"login_form.submit": "Submit",
"election_setup.manifest_menu.title": "Add Election Manifest",
"election_setup.manifest_menu.about": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.manifest_menu.prompt": "Select what you would like to do:",
"election_setup.joint_key_retrieved.title": "Joint Key Retrieved",
"election_setup.joint_key_retrieved.cta": "Create a new election with retrieved key",
"election_setup.joint_key_retrieved.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.joint_key_retrieved.next": "Continue",
"election_setup.joint_key_select.title": "Pull Guardian Keys",
"election_setup.joint_key_select.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.joint_key_select.prompt": "Select Key for Election",
"election_setup.joint_key_select.next": "Pull keys for selected election",
"election_setup.manifest_preview.title": "Election Manifest Uploaded",
"election_setup.manifest_preview.property.name": "Name",
"election_setup.manifest_preview.property.number_of_contests": "Number of Contests",
"election_setup.manifest_preview.property.numberOfStyles": "Number of Ballot Styles",
"election_setup.manifest_preview.property.start_date": "Start Date",
"election_setup.manifest_preview.property.end_date": "End Date",
"election_setup.manifest_preview.property.file_hash": "File Hash",
"election_setup.manifest_preview.property.file_name": "File Name",
"election_setup.manifest_preview.caption": "Preview of Manifest",
"election_setup.manifest_preview.next": "Submit",
"election_setup.manifest_preview.back_to_menu": "Cancel",
"election_setup.upload_manifest.title": "Upload Election Manifest",
"election_setup.upload_manifest.upload": "Select Files to Upload",
"election_setup.upload_manifest.error": "Manifest upload failed",
"election_setup.setup_complete.title": "Congratulations, the election is ready.",
"election_setup.setup_complete.next": "Return to Election List",
"election_setup.introduction.title": "Welcome to the Election Setup",
"election_setup.introduction.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.introduction.next": "Continue",
"election_setup.introduction.steps_heading": "Here's what to expect",
"election_setup.introduction.steps_instruction": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.introduction.step1": "<bold>Lorem ipsum dolor sit amet</bold>, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.introduction.step2": "<primary>Lorem ipsum dolor sit amet</primary>, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.introduction.step3": "<secondary>Lorem ipsum dolor sit amet</secondary>, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_setup.introduction.step4": "<italic>Lorem ipsum dolor sit amet</italic>, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_list.title": "Election List",
"election_list.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"election_list.go_home": "Return to Home",
"joint_key_setup.key_setup.title": "Define Key Requirements",
"joint_key_setup.key_setup.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"joint_key_setup.key_setup.key_heading": "Name your joint key",
"joint_key_setup.key_setup.number_of_guardians_heading": "How many total guardians for this election?",
"joint_key_setup.key_setup.number_of_guardians_emphasis": "Intended Number:",
"joint_key_setup.key_setup.number_of_guardians_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"joint_key_setup.key_setup.quorum_heading": "Select a quorum number for this key.",
"joint_key_setup.key_setup.quorum_emphasis": "What is the quorum and why is it important?",
"joint_key_setup.key_setup.quorum_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"joint_key_setup.key_setup_review.title": "Review and Confirm",
"joint_key_setup.guardian_assignment.title": "Assign Guardians",
"joint_key_setup.guardian_assignment.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"joint_key_setup.guardian_assignment.assigned_label": "Guardians Assigned",
"joint_key_setup.guardian_assignment.no_guardians": "You currently have no guardians for this election. You have not met your quorum.",
"joint_key_setup.guardian_assignment.assign": "Assign Guardian",
"joint_key_setup.guardian_assignment_review.title": "Review and Confirm",
"joint_key_setup.guardian_assignment_review.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"joint_key_setup.guardian_assignment_review.confirmation_callout": "If all the information is correct, please confirm",
"joint_key_setup.guardian_assignment_review.confirmation": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony_list.title": "Join a Key Ceremony",
"key_ceremony_list.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"joint_key_list.title": "Joint Encryption Keys",
"joint_key_list.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.title": "Welcome to the Key Ceremony",
"key_ceremony.introduction.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.button": "Continue",
"key_ceremony.introduction.steps_heading": "Here's what to expect",
"key_ceremony.introduction.steps_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.step1": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.step2": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.step3": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.step4": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.step5": "<italic>Lorem ipsum dolor sit amet</italic>, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.step6": "<italic>Lorem ipsum dolor sit amet</italic>, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.introduction.step7": "<italic>Lorem ipsum dolor sit amet</italic>, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.meet_guardians.title": "Meet the Guardians",
"key_ceremony.meet_guardians.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.meet_guardians.guardian_heading": "Guardians for this election:",
"key_ceremony.meet_guardians.button": "Start Key Ceremony",
"key_ceremony.create_keypair.title": "Create your Election Key Pair",
"key_ceremony.create_keypair.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.create_keypair.button": "Generate Election Key Pair",
"key_ceremony.share_public_key.title": "Share your Public Key",
"key_ceremony.share_public_key.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.share_public_key.button": "Share Public Key",
"key_ceremony.create_backups.title": "Create your Partial Key Backups",
"key_ceremony.create_backups.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.create_backups.button": "Generate Partial Key Backups",
"key_ceremony.create_backups.disabled_button": "Awaiting Other Guardians",
"key_ceremony.share_backups.title": "Share your Partial Key Backups",
"key_ceremony.share_backups.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.share_backups.button": "Share Partial Key Backups",
"key_ceremony.verify_backups.title": "Verify Backups",
"key_ceremony.verify_backups.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.verify_backups.button": "Confirm Backups Verified",
"key_ceremony.verify_backups.disabled_button": "Awaiting Verifications",
"key_ceremony.combine_keys.title": "Combine Public Keys into Joint Key",
"key_ceremony.combine_keys.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.combine_keys.button": "Form Joint Key",
"key_ceremony.combine_keys.disabled_button": "Awaiting Guardians",
"key_ceremony.complete.title": "Key Ceremony Complete",
"key_ceremony.complete.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"key_ceremony.complete.button": "Return to Home",
"key_ceremony.visualization_complete": "Joint Key Created",
"key_ceremony.steps.instructions": "Instructions",
"key_ceremony.steps.meet_guardians": "Meet the Guardians",
"key_ceremony.steps.create_keypair": "Create Election KeyPair",
"key_ceremony.steps.share_public_key": "Share Election Public Key",
"key_ceremony.steps.create_backups": "Create Partial Key Backups",
"key_ceremony.steps.share_backups": "Share Partial Key Backups",
"key_ceremony.steps.verify_backups": "Verify Partial Key Backups",
"key_ceremony.steps.combine_keys": "Form Joint Key",
"key_ceremony.steps.complete": "Key Ceremony Complete",
"tally_ceremony.introduction.title": "Welcome to the Tally Ceremony",
"tally_ceremony.introduction.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.introduction.button": "Continue",
"tally_ceremony.introduction.steps_heading": "Here's what to expect:",
"tally_ceremony.introduction.steps_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.introduction.step1": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.introduction.step2": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.introduction.step3": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.introduction.step4": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.download_tally.title": "Download Encrypted Tally",
"tally_ceremony.download_tally.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.download_tally.button": "Download",
"tally_ceremony.decrypt_tally_share.title": "Decrypt Your Share",
"tally_ceremony.decrypt_tally_share.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.decrypt_tally_share.button": "Decrypt",
"tally_ceremony.decrypt_tally_share.decrypting": "Decrypting. Decryption may take a while",
"tally_ceremony.decrypt_tally_share.complete": "Decryption Complete",
"tally_ceremony.decrypt_tally_share.complete_button": "Continue",
"tally_ceremony.upload_tally_share.title": "Upload Your Share",
"tally_ceremony.upload_tally_share.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.upload_tally_share.button": "Upload",
"tally_ceremony.decrypt_missing.title": "Decrypt Missing Guardian Shares",
"tally_ceremony.decrypt_missing.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.decrypt_missing.button": "Decrypt",
"tally_ceremony.decrypt_missing.decrypting": "Decrypting. Decryption may take a while",
"tally_ceremony.decrypt_missing.complete": "Decryption Complete",
"tally_ceremony.decrypt_missing.complete_button": "Continue",
"tally_ceremony.no_missing.title": "No Missing Guardians",
"tally_ceremony.no_missing.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.no_missing.button": "Skip",
"tally_ceremony.upload_missing.title": "Upload Missing Guardian Shares",
"tally_ceremony.upload_missing.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.upload_missing.button": "Upload",
"tally_ceremony.combine_shares.title": "Combine Shares",
"tally_ceremony.combine_shares.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.combine_shares.button": "Combine",
"tally_ceremony.combine_shares.button_disabled": "Awaiting other guardians",
"tally_ceremony.complete.title": "Tally Ceremony is Complete",
"tally_ceremony.complete.description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.",
"tally_ceremony.complete.button": "Return to Home",
"tally_ceremony.steps.introduction": "Introduction",
"tally_ceremony.steps.download_tally": "Download Encrypted Tally",
"tally_ceremony.steps.decrypt_tally_share": "Decrypt Tally Share",
"tally_ceremony.steps.upload_tally_share": "Upload Tally Share",
"tally_ceremony.steps.decrypt_missing": "Decrypt Share of Missing",
"tally_ceremony.steps.upload_missing": "Upload Share of Missing",
"tally_ceremony.steps.combine_shares": "Combine Shares",
"tally_ceremony.steps.tally_complete": "Tally Ceremony Complete",
"joint_key.name": "Name",
"joint_key.number_of_guardians": "Number of Guardians",
"joint_key.quorum": "Quorum",
"guardian": "Guardian",
"guardian.name": "Name",
"placeholder.processing": "Processing",
"placeholder.complete": "Complete",
"placeholder.error": "Error",
"actions.cancel": "Cancel",
"actions.submit": "Submit",
"actions.confirm": "Confirm",
"actions.next": "Next",
"actions.back": "Back",
"actions.continue": "Continue",
"actions.previous": "Previous",
"actions.edit": "Edit",
"nav.return_home": "Return to Home",
"task_status.error": "Error",
"task_status.complete": "Complete",
"task_status.incomplete": "Incomplete"
}

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,9 +0,0 @@
export * from './GenericMessage';
export * from './Language';
export { default as Locale } from './Locale';
export * from './loremIpsum';
// TODO Remove redundant language files
export { default as MessageId } from './MessageId';
export * from './Message';

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,4 +0,0 @@
export const loremIpsum =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis feugiat magna nec nibh congue, non pretium mauris feugiat. Nam commodo ultrices semper. Praesent hendrerit ut nibh nec mollis. Ut fermentum maximus nibh nec vulputate. Fusce ultricies, arcu quis faucibus egestas, ligula tellus placerat orci, sed scelerisque nisl mi eu nisi. Quisque pulvinar justo justo, non tristique enim pretium non. Cras eu lacus gravida, eleifend magna at, ultricies tortor.';
export default loremIpsum;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,44 +0,0 @@
import { Box, CircularProgress, makeStyles } from '@material-ui/core';
import React from 'react';
import AppBar from '../components/AppBar';
import Footer from '../components/Footer';
const useStyles = makeStyles((theme) => ({
root: {
minHeight: '100vh',
},
loader: {
padding: theme.spacing(5),
},
}));
export interface DefaultLayoutProps {
isLoading?: boolean;
}
export const DefaultLayout: React.FC<DefaultLayoutProps> = ({ children, isLoading = false }) => {
const classes = useStyles();
return (
<Box className={classes.root} height="100vh" display="flex" flexDirection="column">
<AppBar title="Admin App" loggedIn />
<Box display="flex" flexDirection="column" flexGrow={1}>
{isLoading ? (
<Box
display="flex"
alignItems="center"
justifyContent="center"
className={classes.loader}
>
<CircularProgress size={100} />
</Box>
) : (
children
)}
</Box>
<Footer />
</Box>
);
};
export default DefaultLayout;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,71 +0,0 @@
import { Button, Container, Grid, makeStyles } from '@material-ui/core';
import { Home } from '@material-ui/icons';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import InternationalText from '../components/InternationalText';
import { Message, MessageId } from '../lang';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
content: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4),
},
buttonIcon: {
marginRight: theme.spacing(1),
},
spaced: {
marginBottom: theme.spacing(2),
},
}));
export interface ListPageLayoutProps {
title: Message;
description: Message;
goHome?: () => void;
}
export const ListPageLayout: React.FC<ListPageLayoutProps> = ({
title,
description,
goHome,
children,
}) => {
const classes = useStyles();
return (
<Grid container className={classes.root}>
<Container maxWidth="lg" className={classes.content}>
<InternationalText
className={classes.spaced}
variant="h3"
component="h1"
id={title.id}
defaultMessage={title.defaultMessage}
/>
<InternationalText
className={classes.spaced}
id={description.id}
defaultMessage={description.defaultMessage}
/>
<Button
className={classes.spaced}
variant="contained"
color="secondary"
onClick={goHome}
>
<Home className={classes.buttonIcon} />
<FormattedMessage id={MessageId.Nav_Return_Home} />
</Button>
{children}
</Container>
</Grid>
);
};
export default ListPageLayout;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,17 +0,0 @@
import { Box } from '@material-ui/core';
import React from 'react';
import AppBar from '../components/AppBar';
import Footer from '../components/Footer';
export const LoginLayout: React.FC = ({ children }) => (
<Box height="100vh" display="flex" flexDirection="column">
<AppBar />
<Box display="flex" flexDirection="column" flexGrow={1}>
{children}
</Box>
<Footer />
</Box>
);
export default LoginLayout;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,3 +0,0 @@
export * from './DefaultLayout';
export * from './ListPageLayout';
export * from './LoginLayout';

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,11 +0,0 @@
import React from 'react';
import { Box } from '@material-ui/core';
const BallotConfirmationPage: React.FC = ({ children }) => (
<Box height="100vh" display="flex" flexDirection="column">
{children}
<h1> Ballot Confirmation Page</h1>
</Box>
);
export default BallotConfirmationPage;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,11 +0,0 @@
import React from 'react';
import { Box } from '@material-ui/core';
const ElectionPage: React.FC = ({ children }) => (
<Box height="100vh" display="flex" flexDirection="column">
{children}
<h1> Election Page</h1>
</Box>
);
export default ElectionPage;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,11 +0,0 @@
import React from 'react';
import { Box } from '@material-ui/core';
const RecordsPage: React.FC = ({ children }) => (
<Box height="100vh" display="flex" flexDirection="column">
{children}
<h1> Records Page</h1>
</Box>
);
export default RecordsPage;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,11 +0,0 @@
import React from 'react';
import { Box } from '@material-ui/core';
const ResultsPage: React.FC = ({ children }) => (
<Box height="100vh" display="flex" flexDirection="column">
{children}
<h1> Results Page</h1>
</Box>
);
export default ResultsPage;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,11 +0,0 @@
import React from 'react';
import { Box } from '@material-ui/core';
const SelectElectionPage: React.FC = ({ children }) => (
<Box height="100vh" display="flex" flexDirection="column">
{children}
<h1> Select Election Page</h1>
</Box>
);
export default SelectElectionPage;

1
packages/result-app/src/react-app-env.d.ts поставляСмый
ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1 +0,0 @@
/// <reference types="react-scripts" />

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,16 +0,0 @@
import { ReportHandler } from 'web-vitals';
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,20 +0,0 @@
import React from 'react';
import { Route, Routes, Navigate } from 'react-router-dom';
import ElectionPage from '../pages/ElectionPage';
import RecordsPage from '../pages/RecordsPage';
import ResultsPage from '../pages/ResultsPage';
import BallotConfirmationPage from '../pages/BallotConfirmationPage';
import SelectElectionPage from '../pages/SelectElectionPage';
const MainRoutes: React.FC = () => (
<Routes>
<Route path="/" element={<Navigate to="/menu" />} />
<Route path="/menu" element={<SelectElectionPage />} />
<Route path="/:election" element={<ElectionPage />} />
<Route path="/:election/results" element={<ResultsPage />} />
<Route path="/:election/records" element={<RecordsPage />} />
<Route path="/:election/:ballot" element={<BallotConfirmationPage />} />
</Routes>
);
export default MainRoutes;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,5 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,5 +0,0 @@
export type EnumDictionary<T extends string | symbol | number, U> = {
[K in T]: U;
};
export default EnumDictionary;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,19 +0,0 @@
interface EnumStepper<TEnumValue extends number> {
nextStep: (step: TEnumValue) => TEnumValue;
previousStep: (step: TEnumValue) => TEnumValue;
}
export function createEnumStepper<T extends string, TEnumValue extends number>(stepEnum: {
[key in T]: TEnumValue;
}): EnumStepper<TEnumValue> {
return {
nextStep: (step: TEnumValue) =>
step + 1 >= Object.keys(stepEnum).length / 2
? (0 as TEnumValue)
: ((step + 1) as TEnumValue),
previousStep: (step: TEnumValue) =>
step - 1 < 0 ? (0 as TEnumValue) : ((step - 1) as TEnumValue),
};
}
export default EnumStepper;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,8 +0,0 @@
export const delay = (ms: number): Promise<unknown> =>
new Promise((res) => {
setTimeout(() => {
res(true);
}, ms);
});
export default delay;

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,3 +0,0 @@
export * from './delay';
export * from './EnumDictionary';
export * from './EnumStepper';

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„Π°ΠΉΠ»

@ -1,21 +0,0 @@
{
"compilerOptions": {
"module": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"moduleResolution": "node",
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"target": "esnext"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}