i18n for quick-dapp

pull/5060/head
drafish 5 months ago committed by yann300
parent ed54f645f7
commit c489febfdd
  1. 39
      apps/quick-dapp/src/App.tsx
  2. 6
      apps/quick-dapp/src/components/ContractGUI/index.tsx
  3. 24
      apps/quick-dapp/src/components/CreateInstance/index.tsx
  4. 55
      apps/quick-dapp/src/components/DeployPanel/index.tsx
  5. 3
      apps/quick-dapp/src/components/DeployPanel/theme.tsx
  6. 6
      apps/quick-dapp/src/components/EditInstance/index.tsx
  7. 6
      apps/quick-dapp/src/components/ImageUpload/index.tsx
  8. 6
      apps/quick-dapp/src/components/MultipleContainers/index.tsx
  9. 40
      apps/remix-ide/src/app/tabs/locales/en/quickDapp.json

@ -1,4 +1,5 @@
import React, { useEffect, useReducer } from 'react';
import React, { useEffect, useReducer, useState } from 'react';
import { IntlProvider } from 'react-intl'
import CreateInstance from './components/CreateInstance';
import EditInstance from './components/EditInstance';
import DeployPanel from './components/DeployPanel';
@ -15,6 +16,10 @@ import remixClient from './remix-client';
import './App.css';
function App(): JSX.Element {
const [locale, setLocale] = useState<{code: string; messages: any}>({
code: 'en',
messages: null,
})
const [appState, dispatch] = useReducer(appReducer, appInitialState);
useEffect(() => {
updateState(appState);
@ -29,6 +34,14 @@ function App(): JSX.Element {
remixClient.on('theme', 'themeChanged', (theme: any) => {
selectTheme(theme.name);
});
// @ts-ignore
remixClient.call('locale', 'currentLocale').then((locale: any) => {
setLocale(locale)
})
// @ts-ignore
remixClient.on('locale', 'localeChanged', (locale: any) => {
setLocale(locale)
})
});
}, []);
return (
@ -38,17 +51,19 @@ function App(): JSX.Element {
appState,
}}
>
{Object.keys(appState.instance.abi).length > 0 ? (
<div className="row m-0 pt-3">
<EditInstance />
<DeployPanel />
</div>
) : (
<div className="row m-0 pt-3">
<CreateInstance />
</div>
)}
<LoadingScreen />
<IntlProvider locale={locale.code} messages={locale.messages}>
{Object.keys(appState.instance.abi).length > 0 ? (
<div className="row m-0 pt-3">
<EditInstance />
<DeployPanel />
</div>
) : (
<div className="row m-0 pt-3">
<CreateInstance />
</div>
)}
<LoadingScreen />
</IntlProvider>
</AppContext.Provider>
);
}

@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import { execution } from '@remix-project/remix-lib';
import { saveDetails, saveTitle } from '../../actions';
@ -12,6 +13,7 @@ const getFuncABIInputs = (funABI: any) => {
};
export function ContractGUI(props: { funcABI: any }) {
const intl = useIntl()
const isConstant =
props.funcABI.constant !== undefined ? props.funcABI.constant : false;
const lookupOnly =
@ -68,7 +70,7 @@ export function ContractGUI(props: { funcABI: any }) {
<div className="p-2">
<input
className="form-control"
placeholder="Title of function"
placeholder={intl.formatMessage({ id: 'quickDapp.functionTitle' })}
value={props.funcABI.title}
onChange={({ target: { value } }) => {
saveTitle({ id: props.funcABI.id, title: value });
@ -116,7 +118,7 @@ export function ContractGUI(props: { funcABI: any }) {
<div className="p-2">
<textarea
className="form-control"
placeholder="Instructions for function"
placeholder={intl.formatMessage({ id: 'quickDapp.functionInstructions' })}
value={props.funcABI.details}
onChange={({ target: { value } }) => {
saveDetails({ id: props.funcABI.id, details: value });

@ -1,8 +1,10 @@
import React, { useState } from 'react';
import { Alert, Button, Form } from 'react-bootstrap';
import { FormattedMessage, useIntl } from 'react-intl';
import { initInstance } from '../../actions';
const CreateInstance: React.FC = () => {
const intl = useIntl()
const [formVal, setFormVal] = useState({
address: '',
abi: [],
@ -18,10 +20,10 @@ const CreateInstance: React.FC = () => {
}}
>
<Form.Group className="mb-2" controlId="formAddress">
<Form.Label className="text-uppercase mb-0">address</Form.Label>
<Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.address" /></Form.Label>
<Form.Control
type="address"
placeholder="Enter address"
placeholder={intl.formatMessage({ id: 'quickDapp.enterAddress' })}
value={formVal.address}
onChange={(e) => {
setFormVal({ ...formVal, address: e.target.value });
@ -35,7 +37,7 @@ const CreateInstance: React.FC = () => {
as="textarea"
rows={3}
type="abi"
placeholder="Enter abi"
placeholder={intl.formatMessage({ id: 'quickDapp.enterAbi' })}
value={formVal.abi.length > 0 ? JSON.stringify(formVal.abi) : ''}
onChange={(e) => {
let abi = [];
@ -50,10 +52,10 @@ const CreateInstance: React.FC = () => {
</Form.Group>
<Form.Group className="mb-2" controlId="formName">
<Form.Label className="text-uppercase mb-0">name</Form.Label>
<Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.name" /></Form.Label>
<Form.Control
type="name"
placeholder="Enter name"
placeholder={intl.formatMessage({ id: 'quickDapp.enterName' })}
value={formVal.name}
onChange={(e) => {
setFormVal({ ...formVal, name: e.target.value });
@ -62,10 +64,10 @@ const CreateInstance: React.FC = () => {
</Form.Group>
<Form.Group className="mb-2" controlId="formNetwork">
<Form.Label className="text-uppercase mb-0">network</Form.Label>
<Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.network" /></Form.Label>
<Form.Control
type="network"
placeholder="Enter network"
placeholder={intl.formatMessage({ id: 'quickDapp.enterNetwork' })}
value={formVal.network}
onChange={(e) => {
setFormVal({ ...formVal, network: e.target.value });
@ -83,14 +85,12 @@ const CreateInstance: React.FC = () => {
!formVal.abi.length
}
>
Submit
<FormattedMessage id="quickDapp.submit" />
</Button>
<Alert className="mt-4" variant="info">
Dapp Draft only work for Injected Provider currently. More providers
will be adapted in further iterations.
<FormattedMessage id="quickDapp.text1" />
<br />
Click the edit icon in a deployed contract will input the parameters
automatically.
<FormattedMessage id="quickDapp.text2" />
</Alert>
<img src='./assets/edit-dapp.png' />
</Form>

@ -1,5 +1,6 @@
import React, { useContext, useState } from 'react';
import { Form, Button, Alert, InputGroup } from 'react-bootstrap';
import { FormattedMessage, useIntl } from 'react-intl';
import {
deploy,
emptyInstance,
@ -11,6 +12,7 @@ import { CustomTooltip } from '@remix-ui/helper';
import { AppContext } from '../../contexts';
function DeployPanel(): JSX.Element {
const intl = useIntl()
const { appState, dispatch } = useContext(AppContext);
const { verified, natSpec, noTerminal } = appState.instance;
const [formVal, setFormVal] = useState<any>({
@ -36,13 +38,13 @@ function DeployPanel(): JSX.Element {
});
return (
<div className="col-3 d-inline-block">
<h3 className="mb-3">QuickDapp Admin</h3>
<h3 className="mb-3">QuickDapp <FormattedMessage id="quickDapp.admin" /></h3>
<Button
onClick={() => {
resetInstance();
}}
>
Reset Functions
<FormattedMessage id="quickDapp.resetFunctions" />
</Button>
<Button
className="ml-3"
@ -50,16 +52,19 @@ function DeployPanel(): JSX.Element {
emptyInstance();
}}
>
Delete Dapp
<FormattedMessage id="quickDapp.deleteDapp" />
</Button>
<Alert variant="info" className="my-2">
QuickDapp deploys to Surge.sh. Surge accounts are free until you reach a
level of use. The email & password you input below will register you
with a Surge account. The subdomain is your choice but it must be
unique. More about{' '}
<a target="_blank" href="https://surge.sh/help/">
surge.sh
</a>
<FormattedMessage
id="quickDapp.text3"
values={{
a: (chunks) => (
<a target="_blank" href="https://surge.sh/help/">
{chunks}
</a>
),
}}
/>
</Alert>
<Form
onSubmit={(e) => {
@ -71,10 +76,10 @@ function DeployPanel(): JSX.Element {
}}
>
<Form.Group className="mb-2" controlId="formEmail">
<Form.Label className="text-uppercase mb-0">Email</Form.Label>
<Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.email" /></Form.Label>
<Form.Control
type="email"
placeholder="Surge email"
placeholder={intl.formatMessage({ id: 'quickDapp.surgeEmail' })}
required
value={formVal.email}
onChange={(e) => {
@ -83,10 +88,10 @@ function DeployPanel(): JSX.Element {
/>
</Form.Group>
<Form.Group className="mb-2" controlId="formPassword">
<Form.Label className="text-uppercase mb-0">Password</Form.Label>
<Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.password" /></Form.Label>
<Form.Control
type="password"
placeholder="Surge password"
placeholder={intl.formatMessage({ id: 'quickDapp.surgePassword' })}
required
value={formVal.password}
onChange={(e) => {
@ -95,12 +100,12 @@ function DeployPanel(): JSX.Element {
/>
</Form.Group>
<Form.Group className="mb-2" controlId="formPassword">
<Form.Label className="text-uppercase mb-0">Subdomain</Form.Label>
<Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.subdomain" /></Form.Label>
<InputGroup>
<InputGroup.Text>https://</InputGroup.Text>
<Form.Control
type="subdomain"
placeholder="Unique subdomain name"
placeholder={intl.formatMessage({ id: 'quickDapp.uniqueSubdomain' })}
required
value={formVal.subdomain}
onChange={(e) => {
@ -123,7 +128,7 @@ function DeployPanel(): JSX.Element {
</Form.Group> */}
<Form.Group className="mb-2" controlId="formShareTo">
<Form.Label className="text-uppercase mb-0">
Share To (Optional)
<FormattedMessage id="quickDapp.shareTo" />
</Form.Label>
<br />
<div className="d-inline-flex align-items-center custom-control custom-checkbox">
@ -171,7 +176,7 @@ function DeployPanel(): JSX.Element {
</Form.Group>
<Form.Group className="mb-2" controlId="formShareTo">
<Form.Label className="text-uppercase mb-0">
Use NatSpec (Optional)
<FormattedMessage id="quickDapp.useNatSpec" />
</Form.Label>
<br />
<span
@ -184,7 +189,7 @@ function DeployPanel(): JSX.Element {
>
<CustomTooltip
placement="top"
tooltipText="Retrieve info from the contract's NatSpec"
tooltipText={intl.formatMessage({ id: 'quickDapp.useNatSpecTooltip' })}
>
<i
className={
@ -198,7 +203,7 @@ function DeployPanel(): JSX.Element {
</Form.Group>
<Form.Group className="mb-2" controlId="formVerified">
<Form.Label className="text-uppercase mb-0">
Verified by Etherscan (Optional)
<FormattedMessage id="quickDapp.verifiedByEtherscan" />
</Form.Label>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input
@ -219,13 +224,13 @@ function DeployPanel(): JSX.Element {
className="m-0 form-check-label custom-control-label"
style={{ paddingTop: 1 }}
>
Verified
<FormattedMessage id="quickDapp.verified" />
</label>
</div>
</Form.Group>
<Form.Group className="mb-2" controlId="formNoTerminal">
<Form.Label className="text-uppercase mb-0">
No Terminal (Optional)
<FormattedMessage id="quickDapp.noTerminal" />
</Form.Label>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input
@ -246,7 +251,7 @@ function DeployPanel(): JSX.Element {
className="m-0 form-check-label custom-control-label"
style={{ paddingTop: 1 }}
>
No Terminal
<FormattedMessage id="quickDapp.no" />
</label>
</div>
</Form.Group>
@ -260,11 +265,11 @@ function DeployPanel(): JSX.Element {
{deployState.loading && (
<i className="fas fa-spinner fa-spin mr-1"></i>
)}
Deploy
<FormattedMessage id="quickDapp.deploy" />
</Button>
{deployState.code === 'SUCCESS' && (
<Alert variant="success" className="mt-4">
Deployed successfully! <br /> Click the link below to view your dapp
<FormattedMessage id="quickDapp.text4" /> <br /> <FormattedMessage id="quickDapp.text5" />
<br />
<a
target="_blank"

@ -1,4 +1,5 @@
import { Ref, useContext, useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { AppContext } from '../../contexts';
import { selectTheme } from '../../actions';
import { Dropdown } from 'react-bootstrap';
@ -121,7 +122,7 @@ export function ThemeUI() {
return (
<div className="d-block">
<label className="text-uppercase mb-0">Themes</label>
<label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.themes" /></label>
<Dropdown className="w-100">
<Dropdown.Toggle
as={CustomToggle}

@ -1,10 +1,12 @@
import { useContext } from 'react';
import { omitBy } from 'lodash';
import { useIntl } from 'react-intl';
import { MultipleContainers } from '../MultipleContainers';
import { AppContext } from '../../contexts';
import ImageUpload from '../ImageUpload'
function EditInstance(): JSX.Element {
const intl = useIntl()
const { appState, dispatch } = useContext(AppContext);
const { abi, items, containers, title, details, userInput, natSpec } =
appState.instance;
@ -16,7 +18,7 @@ function EditInstance(): JSX.Element {
<div className="my-2 p-3 bg-light">
<input
className="form-control"
placeholder="Dapp title"
placeholder={intl.formatMessage({ id: 'quickDapp.dappTitle' })}
value={title}
onChange={({ target: { value } }) => {
dispatch({
@ -35,7 +37,7 @@ function EditInstance(): JSX.Element {
<div className="my-2 p-3 bg-light">
<textarea
className="form-control"
placeholder="Dapp instructions"
placeholder={intl.formatMessage({ id: 'quickDapp.dappInstructions' })}
value={details}
onChange={({ target: { value } }) => {
dispatch({

@ -1,8 +1,10 @@
import React, { useContext, useEffect, useState } from 'react'
import { useIntl } from 'react-intl';
import { CustomTooltip } from '@remix-ui/helper';
import { AppContext } from '../../contexts'
const ImageUpload = () => {
const intl = useIntl()
const { appState, dispatch } = useContext(AppContext)
const { logo } = appState.instance
const [preview, setPreview] = useState(null)
@ -31,9 +33,9 @@ const ImageUpload = () => {
<input className="d-none" type="file" accept="image/*" onChange={handleImageChange} id="upload-button" />
<CustomTooltip
placement="right"
tooltipText="Click here to change logo"
tooltipText={intl.formatMessage({ id: 'quickDapp.uploadLogoTooltip' })}
>
<label htmlFor="upload-button" className="cursor_pointer d-flex justify-content-center align-items-center position-relative" style={{height: 170}}>
<label htmlFor="upload-button" className="cursor_pointer d-flex justify-content-center align-items-center position-relative" style={{ height: 170 }}>
{logo ? (
<img src={preview} alt="preview" style={{ width: 120, height: 120 }} />
) : (

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { createPortal, unstable_batchedUpdates } from 'react-dom';
import { FormattedMessage, useIntl } from 'react-intl';
import {
CancelDrop,
closestCenter,
@ -173,6 +174,7 @@ export function MultipleContainers({
vertical = false,
scrollable,
}: Props) {
const intl = useIntl()
const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);
const lastOverId = useRef<UniqueIdentifier | null>(null);
const recentlyMovedToNewContainer = useRef(false);
@ -442,7 +444,7 @@ export function MultipleContainers({
<DroppableContainer
key={containerId}
id={containerId}
label={`Column ${containerId}`}
label={`${intl.formatMessage({ id: 'quickDapp.column' })} ${containerId}`}
columns={columns}
items={items[containerId]}
style={containerStyle}
@ -485,7 +487,7 @@ export function MultipleContainers({
onClick={handleAddColumn}
placeholder
>
+ Add column
+ <FormattedMessage id='quickDapp.addColumn' />
</DroppableContainer>
)}
</SortableContext>

@ -0,0 +1,40 @@
{
"quickDapp.address": "address",
"quickDapp.enterAddress": "Enter address",
"quickDapp.enterAbi": "Enter abi",
"quickDapp.name": "name",
"quickDapp.enterName": "Enter name",
"quickDapp.network": "network",
"quickDapp.enterNetwork": "Enter network",
"quickDapp.submit": "Submit",
"quickDapp.text1": "QuickDapp only work for Injected Provider currently. More providers will be adapted in further iterations.",
"quickDapp.text2": "Click the edit icon in a deployed contract will input the parameters automatically.",
"quickDapp.admin": "Admin",
"quickDapp.resetFunctions": "Reset Functions",
"quickDapp.deleteDapp": "Delete Dapp",
"quickDapp.text3": "QuickDapp deploys to Surge.sh. Surge accounts are free until you reach a level of use. The email & password you input below will register you with a Surge account. The subdomain is your choice but it must be unique. More about <a>surge.sh</a>",
"quickDapp.email": "Email",
"quickDapp.surgeEmail": "Surge email",
"quickDapp.password": "Password",
"quickDapp.surgePassword": "Surge password",
"quickDapp.subdomain": "Subdomain",
"quickDapp.uniqueSubdomain": "Unique subdomain name",
"quickDapp.shareTo": "Share To (Optional)",
"quickDapp.useNatSpec": "Use NatSpec (Optional)",
"quickDapp.useNatSpecTooltip": "Retrieve info from the contract's NatSpec",
"quickDapp.verifiedByEtherscan": "Verified by Etherscan (Optional)",
"quickDapp.verified": "Verified",
"quickDapp.noTerminal": "No Terminal (Optional)",
"quickDapp.no": "No",
"quickDapp.themes": "Themes",
"quickDapp.deploy": "Deploy",
"quickDapp.text4": "Deployed successfully!",
"quickDapp.text5": "Click the link below to view your dapp",
"quickDapp.uploadLogoTooltip": "Click here to change logo",
"quickDapp.dappTitle": "Dapp Title",
"quickDapp.dappInstructions": "Dapp Instructions",
"quickDapp.functionTitle": "Title of function",
"quickDapp.functionInstructions": "Instructions for function",
"quickDapp.addColumn": "Add column",
"quickDapp.column": "Column"
}
Loading…
Cancel
Save