react-icons/fi#FiX TypeScript Examples
The following examples show how to use
react-icons/fi#FiX.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From dxvote with GNU Affero General Public License v3.0 | 6 votes |
CloseIcon = styled(FiX)`
color: ${({ theme }) => theme.colors.text};
height: 1.5rem;
width: 1.5rem;
&:hover {
cursor: pointer;
opacity: 0.6;
}
`
Example #2
Source File: MobileFilters.tsx From po8klasie with GNU General Public License v3.0 | 6 votes |
MobileFilters: FC<MobileFiltersProps> = ({ onFiltersChange, filtersValues}) => {
let [isOpen, setIsOpen] = useState(false)
const { searchView } = useProjectConfig();
const { filters: filtersConfig } = searchView as SearchViewConfig;
return (
<>
<button
className="rounded-xl border border-light px-3 py-1 mx-2 flex items-center md:hidden"
onClick={() => setIsOpen(!isOpen)}>
<BiFilterAlt className="mr-2" />
Filtry
</button>
<Dialog open={isOpen} onClose={() => setIsOpen(false)}>
<Dialog.Panel className="top-0 left-0 h-full w-full fixed z-40 bg-appBg pt-navbarHeight">
<div className="flex items-center justify-end">
<button className="p-2" onClick={() => setIsOpen(false)}>
<FiX className="text-xl" />
</button>
</div>
{filtersConfig.map(({ options, key, component, displayInRowOnMobile }) => {
const FilterComponent = mobileFiltersComponents[component as keyof typeof mobileFiltersComponents];
if (displayInRowOnMobile) return null;
return (
<FilterComponent
options={options}
onChange={onFiltersChange(key)}
value={filtersValues[key]}
/>
);
})}
</Dialog.Panel>
</Dialog>
</>
)
}
Example #3
Source File: index.tsx From dxvote with GNU Affero General Public License v3.0 | 6 votes |
CloseIcon = styled(FiX)`
position: absolute;
color: ${({ theme }) => theme.colors.text};
right: 1.5rem;
top: 50%;
transform: translateY(-50%);
height: 1.5rem;
width: 1.5rem;
z-index: 800;
&:hover {
cursor: pointer;
opacity: 0.6;
}
`
Example #4
Source File: BetaBanner.tsx From po8klasie with GNU General Public License v3.0 | 6 votes |
BetaBanner = () => {
const shouldBannerBeShownInitially =
typeof window !== 'undefined'
? localStorage.getItem(BANNER_LOCAL_STORAGE_KEY) !== 'true'
: false;
const [shouldBannerBeShown, setShouldBannerBeShown] = useState(shouldBannerBeShownInitially);
const closeBanner = () => {
setShouldBannerBeShown(false);
localStorage.setItem(BANNER_LOCAL_STORAGE_KEY, 'true');
};
if (!shouldBannerBeShown) return null;
return (
<div className="fixed bottom-0 w-full">
<div className="w-container mb-5 w-container mx-auto">
<div className="relative bg-primaryBg backdrop-filter backdrop-blur-2xl bg-opacity-70 border-2 rounded border-primary text-primary px-5 py-2">
<button className="absolute right-2 top-2" onClick={closeBanner}>
<FiX />
</button>
<h4 className="font-bold text-lg">Aplikacja w fazie beta</h4>
<p>
Nie wszystkie funkcje serwisu mogą działać poprawnie. Jeśli zauważysz błąd w działaniu
aplikacji lub chcesz podzielić się sugestią,{' '}
<Link href="/#contact-us">
<a className="underline">skontaktuj siÄ™ z nami</a>
</Link>
.
</p>
</div>
</div>
</div>
);
}
Example #5
Source File: index.tsx From tobira with Apache License 2.0 | 6 votes |
OpenMenuMode: React.FC = () => {
const { t } = useTranslation();
const menu = useMenu();
return <>
<Logo />
<ButtonContainer>
<ActionIcon title={t("close")} onClick={() => menu.close()}>
<FiX />
</ActionIcon>
</ButtonContainer>
</>;
}
Example #6
Source File: Navbar.tsx From po8klasie with GNU General Public License v3.0 | 5 votes |
Navbar: FC<NavbarProps> = ({ navbarWrapperClassName, projectsList }) => {
const [shouldNavbarHaveBackground, setShouldNavbarHaveBackground] = useState(false);
const [isNavbarCollapsed, setNavbarCollapsed] = useState(true);
const { t } = useTranslation('landing');
useEffect(() => {
const handleScroll = () => setShouldNavbarHaveBackground(window.scrollY > 10);
document.addEventListener('scroll', handleScroll);
return () => document.removeEventListener('scroll', handleScroll);
}, []);
return (
<div
className={`fixed top-0 left-0 w-full z-10 transition duration-100 ${
(shouldNavbarHaveBackground || !isNavbarCollapsed) && navbarBgStyle
} ${navbarWrapperClassName ?? ''}`}
>
<div className="w-container mx-auto md:flex justify-between items-center">
<div className="flex justify-between items-center w-full">
<a {...getScrollToSectionProps('top')}>
<Brand className="font-bold text-2xl" />
</a>
<span className="md:hidden" onClick={() => setNavbarCollapsed(!isNavbarCollapsed)}>
{isNavbarCollapsed ? <FiMenu /> : <FiX />}
</span>
</div>
<div
className={`w-full mt-5 md:flex items-center justify-end ${
isNavbarCollapsed && 'hidden'
}`}
>
<ul className="flex md:flex-row flex-col">
{
isFeatureFlagEnabled(publicRuntimeConfig.SHOW_LINKS_TO_APP) && (
<li className="my-1">
<Popover className="relative">
<Popover.Button className="font-bold">{t('navbar.schools')}</Popover.Button>
<Popover.Panel className={popoverPanelClassName}>
<ul>
{projectsList.map(({ projectID, appName }) => (
<li className="ml-2 md:ml-0 my-2">
<a href={`/${projectID}`}>{capitalize(appName)}</a>
</li>
))}
</ul>
</Popover.Panel>
</Popover>
</li>
)
}
<li className="font-bold md:mx-10 my-1">
<Link href="/calculator">
<a>{t('navbar.pointsCalculator')}</a>
</Link>
</li>
</ul>
<span className="block mt-5 md:mt-0 md:ml-5">
<a
{...getScrollToSectionProps('support-us')}
className={[
'font-bold inline-block w-full sm:w-auto text-center',
roundedSmallLinkClassName,
].join(' ')}
>
{t('navbar.supportTheProject')}
</a>
</span>
</div>
</div>
</div>
);
}
Example #7
Source File: Modal.tsx From meshtastic-web with GNU General Public License v3.0 | 5 votes |
Modal = ({
open,
bgDismiss,
onClose,
actions,
...props
}: ModalProps): JSX.Element => {
const darkMode = useAppSelector((state) => state.app.darkMode);
return (
<AnimatePresence>
{open && (
<m.div
className={`fixed inset-0 ${darkMode ? 'dark' : ''} ${
open ? 'z-30' : 'z-0'
}`}
>
<m.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.1 }}
className="fixed h-full w-full backdrop-blur-md backdrop-brightness-75 backdrop-filter"
onClick={(): void => {
bgDismiss && onClose();
}}
/>
<m.div className="text-center ">
<span
className="inline-block h-screen align-middle "
aria-hidden="true"
>
​
</span>
<div className="inline-block w-full max-w-3xl align-middle">
<Card
border
actions={
<div className="flex gap-2">
{actions}
<IconButton
tooltip="Close"
icon={<FiX />}
onClick={onClose}
/>
</div>
}
className="relative flex-col"
{...props}
/>
</div>
</m.div>
</m.div>
)}
</AnimatePresence>
);
}
Example #8
Source File: RangeTable.tsx From HoldemSolver with MIT License | 5 votes |
function RangeTable(props: RangeTableProps): React.ReactElement {
const { className = '' } = props;
const [modalShown, setModalShown] = useState(false);
return (
<RangeTableStyle className={className}>
<Modal
title="Add Range"
shown={modalShown}
closeModal={() => setModalShown(false)}
actionButtons={[
<Button variant="primary" onClick={() => {}}>
Create Range
</Button>,
]}
>
<CreateRangeForm/>
</Modal>
<div className="range-table-container">
<div className="range-table-header">
RANGES
</div>
<table className="range-table">
<thead>
<tr>
<th>POSITION</th>
<th>TITLE</th>
<th>EQUITY</th>
</tr>
</thead>
<tbody>
<tr className="range-table-item">
<td>CO</td>
<td>Limp</td>
<td>32.53%</td>
<td className="range-table-item-icons">
<FiX/>
</td>
</tr>
<tr className="range-table-item range-table-item-active">
<td>UTG+1</td>
<td>Raise first in</td>
<td>56.64%</td>
<td className="range-table-item-icons">
<FiX/>
</td>
</tr>
</tbody>
</table>
<div className="range-table-footer">
<div onClick={() => setModalShown(true)} className="range-table-add">
<FiPlusCircle/>
<div>Add Range</div>
</div>
</div>
</div>
</RangeTableStyle>
);
}
Example #9
Source File: Modal.tsx From tobira with Apache License 2.0 | 5 votes |
Modal = forwardRef<ModalHandle, PropsWithChildren<ModalProps>>(({
title,
closable = true,
children,
}, ref) => {
const [isOpen, setOpen] = useState(false);
useImperativeHandle(ref, () => ({
open: () => setOpen(true),
close: closable ? (() => setOpen(false)) : undefined,
}));
useEffect(() => {
const handleEscape = (event: KeyboardEvent) => {
if (closable && event.key === "Escape") {
setOpen(false);
}
};
window.addEventListener("keydown", handleEscape);
return () => window.removeEventListener("keydown", handleEscape);
}, [closable]);
return ReactDOM.createPortal(
isOpen && <div
{...(closable && { onClick: e => {
if (e.target === e.currentTarget) {
setOpen(false);
}
} })}
css={{
position: "fixed",
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: "rgba(0, 0, 0, 0.8)",
display: "flex",
justifyContent: "center",
alignItems: "center",
zIndex: 2000,
}}
>
<div css={{
backgroundColor: "white",
borderRadius: 4,
width: 400,
maxWidth: "100%",
margin: 16,
}}>
<div css={{
padding: "12px 16px",
borderBottom: "1px solid var(--grey80)",
display: "flex",
alignItems: "center",
}}>
<h2 css={{ flex: "1" }}>{title}</h2>
{closable && <div
onClick={() => setOpen(false)}
css={{ fontSize: 32, cursor: "pointer", display: "inline-flex" }}
><FiX /></div>}
</div>
<div css={{ padding: 16 }}>{children}</div>
</div>
</div>,
document.body,
);
})
Example #10
Source File: index.tsx From rocketredis with MIT License | 5 votes |
Header: React.FC = () => {
const handleCloseWindow = useCallback(() => {
const window = remote.getCurrentWindow()
window.close()
}, [])
const handleMaximize = useCallback(() => {
const window = remote.getCurrentWindow()
const isMacSystem = os.platform() === 'darwin'
if (isMacSystem) {
return window.setFullScreen(!window.isFullScreen())
}
const { width: currentWidth, height: currentHeight } = window.getBounds()
const {
width: maxWidth,
height: maxHeight
} = remote.screen.getPrimaryDisplay().workAreaSize
const isMaximized = currentWidth === maxWidth && currentHeight === maxHeight
if (!isMaximized) {
window.maximize()
} else {
window.unmaximize()
}
}, [])
const handleMinimize = useCallback(() => {
const window = remote.getCurrentWindow()
window.minimize()
}, [])
const useMacOSWindowActionButtons = useConfig('useMacOSWindowActionButtons')
const shouldUseMacOSWindowActions = useMemo(() => {
return useMacOSWindowActionButtons || os.platform() === 'darwin'
}, [useMacOSWindowActionButtons])
return (
<Container>
<strong>Rocket Redis</strong>
{shouldUseMacOSWindowActions ? (
<WindowActions position="left" shouldShowIconsOnHover>
<MacActionButton color="close" onClick={handleCloseWindow}>
<FiX />
</MacActionButton>
<MacActionButton color="minimize" onClick={handleMinimize}>
<FiMinus />
</MacActionButton>
<MacActionButton color="maximize" onClick={handleMaximize}>
<FiMaximize2 />
</MacActionButton>
</WindowActions>
) : (
<WindowActions position="right">
<DefaultActionButton onClick={handleMinimize}>
<FiMinus />
</DefaultActionButton>
<DefaultActionButton onClick={handleMaximize}>
<FiSquare />
</DefaultActionButton>
<DefaultActionButton onClick={handleCloseWindow}>
<FiX />
</DefaultActionButton>
</WindowActions>
)}
</Container>
)
}
Example #11
Source File: index.tsx From vagasExplorer with MIT License | 4 votes |
Repository: React.FC<ToggleTheme> = ({ toggleTheme }) => {
const [repository, setRepositories] = useState<RepositoryProps | null>(null);
const [issues, setIssues] = useState<IssueProps[]>([]);
const [searchValue, setSearchValue] = useState('');
const { params } = useRouteMatch<RepositoryParamsProps>();
const [allIssues, setAllIssues] = useState<IssueProps[]>([]);
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
api.get(`repos/${params.repository}`).then((response) => {
setRepositories(response.data);
});
api.get(`repos/${params.repository}/issues`).then((response) => {
setIssues(response.data);
setAllIssues(response.data);
console.log(response.data);
});
}, [params.repository]);
const handleSearch = (val: string) => {
if (null !== inputRef.current) {
inputRef.current.focus();
}
if (!val) setIssues(allIssues);
setSearchValue(val);
// eslint-disable-next-line
const issuesFiltered = allIssues.filter((issue) => {
if (issue.title.toLowerCase().indexOf(val.toLowerCase()) !== -1) {
return true;
}
if (issue.body.toLowerCase().indexOf(val.toLowerCase()) !== -1) {
return true;
}
for (let i = 0; i < issue.labels.length; i++) {
if (
issue.labels[i].name.toLowerCase().indexOf(val.toLowerCase()) !== -1
) {
return true;
}
}
return false;
});
setIssues(issuesFiltered);
};
return (
<Layout isContentFull>
<Header isLink="/dashboard" toggleTheme={toggleTheme} />
<S.Container>
{repository && (
<S.RepositoryInfo>
<div>
<img
src={repository.owner.avatar_url}
alt={repository.owner.login}
/>
<div>
<strong>{repository.full_name}</strong>
<p>{repository.description}</p>
</div>
</div>
<ul>
<li>
<strong>{repository.open_issues_count}</strong>
<span>Vagas abertas</span>
</li>
</ul>
</S.RepositoryInfo>
)}
<S.Issues>
<>
<S.Search>
<S.Input
ref={inputRef}
type="text"
placeholder="Busque por tecnologia, nÃvel de vaga, local, regime, tipo etc..."
value={searchValue}
onChange={(e) => handleSearch(e.target.value)}
/>
{searchValue && (
<S.Icon onClick={() => handleSearch('')}>
<FiX size={20} />
</S.Icon>
)}
</S.Search>
{issues.map((issue, index) => (
<React.Fragment key={issue.id}>
<a
href={issue.html_url}
style={{ animationDelay: `0.${index}ms` }}
>
<img src={issue.user.avatar_url} alt={issue.user.login} />
<div>
<strong>{issue.title}</strong>
<p>{issue.user.login}</p>
</div>
<FiChevronRight size={20} />
</a>
{issue.labels.length > 0 && (
<S.Labels style={{ animationDelay: `0.${index}ms` }}>
{issue.labels.map((label) => (
<S.Label
color={label.color}
onClick={() => handleSearch(label.name)}
>
<span>{label.name}</span>
</S.Label>
))}
</S.Labels>
)}
</React.Fragment>
))}
</>
</S.Issues>
</S.Container>
</Layout>
);
}
Example #12
Source File: Configuration.tsx From dxvote with GNU Affero General Public License v3.0 | 4 votes |
ConfigPage = observer(() => {
const {
context: {
configStore,
pinataService,
etherscanService,
infuraService,
poktService,
alchemyService,
customRpcService,
},
} = useContext();
const networkName = configStore.getActiveChainName();
const [etherscanApiStatus, setEtherscanApiStatus] = React.useState(
etherscanService.auth
);
const [pinataKeyStatus, setPinataKeyStatus] = React.useState(
pinataService.auth
);
const [infuraKeyStatus, setInfuraKeyStatus] = React.useState(
infuraService.auth
);
const [poktStatus, setPoktStatus] = React.useState(poktService.auth);
const [alchemyKeyStatus, setAlchemyKeyStatus] = React.useState(
alchemyService.auth
);
const [customRpcUrlStatus, setCustomRpcUrlStatus] = React.useState(
customRpcService.auth
);
const [localConfig, setLocalConfig] = React.useState(
configStore.getLocalConfig()
);
const [, forceUpdate] = React.useReducer(x => x + 1, 0);
function onApiKeyValueChange(value, key) {
localConfig[key] = value;
setLocalConfig(localConfig);
forceUpdate();
}
function saveConfig() {
configStore.setLocalConfig(localConfig);
}
async function testApis() {
await pinataService.isAuthenticated();
await etherscanService.isAuthenticated(networkName);
await infuraService.isAuthenticated();
await poktService.isAuthenticated();
await alchemyService.isAuthenticated();
await customRpcService.isAuthenticated();
setPinataKeyStatus(pinataService.auth);
setEtherscanApiStatus(etherscanService.auth);
setInfuraKeyStatus(infuraService.auth);
setPoktStatus(poktService.auth);
setAlchemyKeyStatus(alchemyService.auth);
setCustomRpcUrlStatus(customRpcService.auth);
}
async function pinDXvoteHashes() {
pinataService.updatePinList();
}
async function clearCache() {
localStorage.clear();
caches.delete(`dxvote-cache`);
window.location.reload();
}
return (
<Box centered>
<h2>
API Keys <Question question="8" />
</h2>
<FormContainer>
<Row>
<FormLabel>Etherscan:</FormLabel>
<InputBox
type="text"
serviceName="etherscan"
onChange={event =>
onApiKeyValueChange(event.target.value, 'etherscan')
}
value={localConfig.etherscan}
></InputBox>
<FormLabel>
{etherscanApiStatus ? <FiCheckCircle /> : <FiX />}
</FormLabel>
</Row>
<Row>
<FormLabel>Pinata:</FormLabel>
<InputBox
type="text"
serviceName="pinata"
onChange={event =>
onApiKeyValueChange(event.target.value, 'pinata')
}
value={localConfig.pinata}
></InputBox>
<FormLabel>{pinataKeyStatus ? <FiCheckCircle /> : <FiX />}</FormLabel>
</Row>
<Row>
<FormLabel>RPC:</FormLabel>
<Dropdown
onChange={event =>
onApiKeyValueChange(event.target.value, 'rpcType')
}
value={localConfig.rpcType}
>
<option value="">Default</option>
<option value="pokt">Pokt</option>
<option value="infura">Infura</option>
<option value="alchemy">Alchemy</option>
<option value="custom">Custom</option>
</Dropdown>
</Row>
{localConfig.rpcType === 'pokt' && (
<Row>
<FormLabel>Pokt:</FormLabel>
<InputBox
type="text"
serviceName="pokt"
onChange={event =>
onApiKeyValueChange(event.target.value, 'pokt')
}
value={localConfig.pokt}
></InputBox>
<FormLabel>{poktStatus ? <FiCheckCircle /> : <FiX />}</FormLabel>
</Row>
)}
{localConfig.rpcType === 'infura' && (
<Row>
<FormLabel>Infura:</FormLabel>
<InputBox
type="text"
serviceName="infura"
onChange={event =>
onApiKeyValueChange(event.target.value, 'infura')
}
value={localConfig.infura}
></InputBox>
<FormLabel>
{infuraKeyStatus ? <FiCheckCircle /> : <FiX />}
</FormLabel>
</Row>
)}
{localConfig.rpcType === 'alchemy' && (
<Row>
<FormLabel>Alchemy:</FormLabel>
<InputBox
type="text"
serviceName="alchemy"
onChange={event =>
onApiKeyValueChange(event.target.value, 'alchemy')
}
value={localConfig.alchemy}
></InputBox>
<FormLabel>
{alchemyKeyStatus ? <FiCheckCircle /> : <FiX />}
</FormLabel>
</Row>
)}
{localConfig.rpcType === 'custom' && (
<Row>
<FormLabel>RPC URL:</FormLabel>
<InputBox
type="text"
serviceName="customRpcUrl"
onChange={event =>
onApiKeyValueChange(event.target.value, 'customRpcUrl')
}
value={localConfig.customRpcUrl}
></InputBox>
<FormLabel>
{customRpcUrlStatus ? <FiCheckCircle /> : <FiX />}
</FormLabel>
</Row>
)}
</FormContainer>
<Row>
<FormLabel>Pin DXdao hashes on start</FormLabel>
<InputBox
type="checkbox"
checked={localConfig.pinOnStart}
onChange={event =>
onApiKeyValueChange(event.target.checked, 'pinOnStart')
}
></InputBox>
</Row>
<Row>
<Button onClick={saveConfig}>Save</Button>
<Button onClick={testApis}>Test Apis</Button>
<Button onClick={clearCache}>Clear Cache</Button>
<Button onClick={pinDXvoteHashes}>Pin DXVote Hashes</Button>
</Row>
</Box>
);
})
Example #13
Source File: CreateOrphanage.tsx From happy with MIT License | 4 votes |
export default function CreateOrphanage() {
const history = useHistory();
const [position, setPosition] = useState({ latitude: 0, longitude: 0 });
const [name, setName] = useState('');
const [about, setAbout] = useState('');
const [instructions, setInstructions] = useState('');
const [opening_hours, setOpeningHours] = useState('');
const [open_on_weekends, setOpenOnWeekends] = useState(true);
const [images, setImages] = useState<File[]>([]);
const [previewImages, setPreviewImages] = useState<PreviewImage[]>([]);
function handleMapClick(event: LeafletMouseEvent) {
const { lat, lng } = event.latlng;
setPosition({
latitude: lat,
longitude: lng
});
}
async function handleSubmit(event: FormEvent) {
event.preventDefault();
const { latitude, longitude } = position;
const data = new FormData();
data.append('name', name);
data.append('about', about);
data.append('latitude', String(latitude));
data.append('longitude', String(longitude));
data.append('instructions', instructions);
data.append('opening_hours', opening_hours);
data.append('open_on_weekends', String(open_on_weekends));
images.forEach(image => {
data.append('images', image);
});
await api.post('/orphanages', data);
alert('Orfanato cadastrado com sucesso!');
history.push('/app');
}
function handleSelectImages(event: ChangeEvent<HTMLInputElement>) {
if (!event.target.files) {
return;
}
const selectedImages = Array.from(event.target.files);
event.target.value = "";
setImages(selectedImages);
const selectedImagesPreview = selectedImages.map(image => {
return { name: image.name, url: URL.createObjectURL(image) };
});
setPreviewImages(selectedImagesPreview);
}
function handleRemoveImage(image: PreviewImage) {
setPreviewImages(
previewImages.map((image) => image).filter((img) => img.url !== image.url)
);
setImages(
images.map((image) => image).filter((img) => img.name !== image.name)
);
}
return (
<div id="page-create-orphanage">
<Sidebar />
<main>
<form onSubmit={handleSubmit} className="create-orphanage-form">
<fieldset>
<legend>Dados</legend>
<Map
center={[-27.2092052, -49.6401092]}
style={{ width: '100%', height: 280 }}
zoom={15}
onclick={handleMapClick}
>
<TileLayer
url={`https://api.mapbox.com/styles/v1/mapbox/light-v10/tiles/256/{z}/{x}/{y}@2x?access_token=${process.env.REACT_APP_MAPBOX_TOKEN}`}
/>
{position.latitude !== 0 && (
<Marker
interactive={false}
icon={mapIcon}
position={[
position.latitude,
position.longitude
]}
/>
)}
</Map>
<div className="input-block">
<label htmlFor="name">Nome</label>
<input
id="name"
value={name}
onChange={event => setName(event.target.value)}
/>
</div>
<div className="input-block">
<label htmlFor="about">Sobre <span>Máximo de 300 caracteres</span></label>
<textarea
id="name"
maxLength={300}
value={about}
onChange={event => setAbout(event.target.value)}
/>
</div>
<div className="input-block">
<label htmlFor="images">Fotos</label>
<div className="images-container">
{previewImages.map((image) => {
return (
<div key={image.url}>
<span
className="remove-image"
onClick={() => handleRemoveImage(image)}
>
<FiX size={18} color="#ff669d" />
</span>
<img src={image.url} alt={name} className="new-image" />
</div>
);
})}
<label htmlFor="image[]" className="new-image">
<FiPlus size={24} color="#15b6d6" />
</label>
</div>
<input
type="file"
multiple
accept=".png, .jpg, .jpeg"
onChange={handleSelectImages}
id="image[]"
/>
</div>
</fieldset>
<fieldset>
<legend>Visitação</legend>
<div className="input-block">
<label htmlFor="instructions">Instruções</label>
<textarea
id="instructions"
value={instructions}
onChange={event => setInstructions(event.target.value)}
/>
</div>
<div className="input-block">
<label htmlFor="opening_hours">Horário de Funcionamento</label>
<input
id="opening_hours"
value={opening_hours}
onChange={event => setOpeningHours(event.target.value)}
/>
</div>
<div className="input-block">
<label htmlFor="open_on_weekends">Atende fim de semana</label>
<div className="button-select">
<button
type="button"
className={open_on_weekends ? 'active' : ''}
onClick={() => setOpenOnWeekends(true)}
>
Sim
</button>
<button
type="button"
className={!open_on_weekends ? 'active' : ''}
onClick={() => setOpenOnWeekends(false)}
>
Não
</button>
</div>
</div>
</fieldset>
<button className="confirm-button" type="submit">
Confirmar
</button>
</form>
</main>
</div>
);
}
Example #14
Source File: HardwareModal.tsx From Meshtastic with GNU General Public License v3.0 | 4 votes |
HardwareModal = ({
device,
open,
close,
}: HardwareModal): JSX.Element => {
const [hideDetails, setHideDetails] = useState(false);
const { breakpoint } = useBreakpoint(BREAKPOINTS, 'md');
return (
<Modal open={open} onClose={close}>
<div className="absolute right-0 z-20 m-2 md:flex">
<Button onClick={close}>
<FiX />
</Button>
</div>
<div className="absolute inset-0">
<motion.div
layout
animate={
breakpoint === 'sm'
? hideDetails
? 'hiddenSm'
: 'visibleSm'
: hideDetails
? 'hidden'
: 'visible'
}
variants={{
hidden: { width: '100%', height: '100%' },
hiddenSm: { height: '100%', width: '100%' },
visible: { width: '20%', height: '100%' },
visibleSm: { height: '33%', width: '100%' },
}}
transition={{
type: 'just',
}}
className="flex flex-col md:h-full md:flex-row"
>
<motion.div
layout
className={`relative z-10 flex h-full w-full rounded-t-2xl md:rounded-l-2xl md:rounded-tr-none ${device.misc.Gradient}`}
>
<motion.img
layout
src={device.images.Front}
alt=""
className="pointer-events-none m-auto max-h-full max-w-full object-cover p-2"
/>
<div className="absolute -bottom-5 z-20 flex w-full md:bottom-auto md:-right-5 md:h-full md:w-auto">
<Button
animate={
breakpoint === 'sm'
? hideDetails
? 'hiddenSm'
: 'visibleSm'
: hideDetails
? 'hidden'
: 'visible'
}
variants={{
hidden: { rotate: 180 },
hiddenSm: { rotate: -90 },
visible: { rotate: 0 },
visibleSm: { rotate: 90 },
}}
onClick={() => {
setHideDetails(!hideDetails);
}}
>
<FiChevronRight />
</Button>
</div>
<AnimatePresence>
{!hideDetails && (
<>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className={`absolute -bottom-5 z-20 flex md:mt-0 md:hidden md:pb-2 ${
hideDetails ? 'opacity-0' : 'opacity-100'
}`}
>
<VariantSelectButton options={device.variants} />
</motion.div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute -bottom-3 right-0 m-auto mr-2 ml-auto flex md:inset-x-1 md:bottom-4 md:mt-2"
>
<div className="m-auto flex gap-2">
{device.features.BLE && (
<Badge
name="Bluetooth"
color="bg-blue-500"
icon={<FiBluetooth />}
/>
)}
{device.features.WiFi && (
<Badge
name="WiFi"
color="bg-orange-500"
icon={<FiWifi />}
/>
)}
</div>
</motion.div>
</>
)}
</AnimatePresence>
</motion.div>
<div
className={`h-7 bg-base opacity-0 md:h-auto md:w-7 ${
hideDetails ? 'flex' : 'hidden'
}`}
/>
</motion.div>
</div>
<div className="z-[1] mt-[25%] flex h-full flex-col md:ml-[20%] md:mt-0 md:w-4/5">
<div className="z-0 hidden pb-2 md:flex">
<VariantSelectButton options={device.variants} />
</div>
<div
className={`mt-1 flex flex-grow rounded-2xl bg-base p-2 shadow-inner transition-opacity duration-100 ease-linear md:mt-0 md:rounded-l-none md:rounded-r-2xl md:p-4 ${
hideDetails ? 'opacity-0' : 'opacity-100'
}`}
>
<Tab.Group
as="div"
className="flex flex-grow flex-col rounded-2xl bg-primary p-2"
>
<Tab.List className="flex gap-2">
<CardTab title="Info" />
<CardTab title="Power" />
<CardTab title="Pinout" />
</Tab.List>
<Tab.Panels as="div" className="flex-grow overflow-y-auto">
<InfoTab device={device} />
<PowerTab device={device} />
<PinoutTab device={device} />
</Tab.Panels>
</Tab.Group>
</div>
</div>
</Modal>
);
}
Example #15
Source File: Cache.tsx From dxvote with GNU Affero General Public License v3.0 | 4 votes |
CachePage = observer(() => {
// Set html title to cache to differentiate from dxvote dapp
document.title = 'Cache';
const {
context: { cacheService, configStore, notificationStore, ipfsService },
} = useContext();
const [updateProposalTitles, setUpdateProposalTitles] = React.useState(false);
const [buildingCacheState, setBuildingCacheState] = React.useState(0);
const [updatedCacheHash, setUpdatedCacheHash] = React.useState({
proposalTitles: {},
configHashes: {},
configs: {},
caches: {},
});
const [resetCache, setResetCache] = React.useState({
mainnet: false,
rinkeby: false,
xdai: false,
arbitrum: false,
arbitrumTestnet: false,
});
const [localConfig, setLocalConfig] = React.useState(
configStore.getLocalConfig()
);
const [, forceUpdate] = React.useReducer(x => x + 1, 0);
async function resetCacheOptions() {
configStore.resetLocalConfig();
setLocalConfig(configStore.getLocalConfig());
setBuildingCacheState(0);
setResetCache({
mainnet: false,
rinkeby: false,
xdai: false,
arbitrum: false,
arbitrumTestnet: false,
});
setUpdatedCacheHash({
proposalTitles: {},
configHashes: {},
configs: {},
caches: {},
});
setUpdateProposalTitles(false);
}
async function uploadToIPFS(content) {
ipfsService.upload(content);
}
async function runCacheScript() {
setBuildingCacheState(1);
const updatedCache = await cacheService.getUpdatedCacheConfig(
{
1: {
rpcUrl: localConfig.mainnet_rpcURL,
toBlock: localConfig.mainnet_toBlock,
reset: resetCache.mainnet,
},
4: {
rpcUrl: localConfig.rinkeby_rpcURL,
toBlock: localConfig.rinkeby_toBlock,
reset: resetCache.rinkeby,
},
100: {
rpcUrl: localConfig.xdai_rpcURL,
toBlock: localConfig.xdai_toBlock,
reset: resetCache.xdai,
},
42161: {
rpcUrl: localConfig.arbitrum_rpcURL,
toBlock: localConfig.arbitrum_toBlock,
reset: resetCache.arbitrum,
},
421611: {
rpcUrl: localConfig.arbitrumTestnet_rpcURL,
toBlock: localConfig.arbitrumTestnet_toBlock,
reset: resetCache.arbitrumTestnet,
},
},
updateProposalTitles
);
console.log('[Updated Cache]', updatedCache);
setUpdatedCacheHash(updatedCache);
setBuildingCacheState(2);
forceUpdate();
}
function onApiKeyValueChange(value, key) {
localConfig[key] = value;
setLocalConfig(localConfig);
configStore.setLocalConfig(localConfig);
forceUpdate();
}
function downloadAll() {
var zip = new JSZip();
var cache = zip.folder('cache');
var configs = zip.folder('configs');
zip.file(
'default.json',
JSON.stringify(
{
mainnet: updatedCacheHash.configHashes['mainnet'],
xdai: updatedCacheHash.configHashes['xdai'],
arbitrum: updatedCacheHash.configHashes['arbitrum'],
rinkeby: updatedCacheHash.configHashes['rinkeby'],
arbitrumTestnet: updatedCacheHash.configHashes['arbitrumTestnet'],
},
null,
2
)
);
zip.file(
'proposalTitles.json',
JSON.stringify(updatedCacheHash.proposalTitles, null, 2)
);
NETWORKS.map((network, i) => {
cache.file(
network.name + '.json',
JSON.stringify(updatedCacheHash.caches[network.name], null, 2)
);
const configFolder = configs.folder(network.name);
configFolder.file(
'config.json',
JSON.stringify(updatedCacheHash.configs[network.name], null, 2)
);
});
zip.generateAsync({ type: 'blob' }).then(function (content) {
saveAs(content, 'dxvote-cache.zip');
});
}
if (window.location.hash.length > 7) {
const searchParams = new URLSearchParams(window.location.hash.substring(7));
setUpdateProposalTitles(searchParams.get('proposalTitles') ? true : false);
NETWORKS.map((network, i) => {
const networkName = network.name;
if (searchParams.get(networkName + '_toBlock'))
localConfig[networkName + '_toBlock'] = searchParams.get(
networkName + '_toBlock'
);
if (searchParams.get(networkName + '_targetHash'))
localConfig[networkName + '_targetHash'] = searchParams.get(
networkName + '_targetHash'
);
if (searchParams.get(networkName + '_reset')) {
resetCache[networkName] = true;
}
});
setLocalConfig(localConfig);
setResetCache(resetCache);
configStore.setLocalConfig(localConfig);
window.location.assign(window.location.origin + '/#cache');
forceUpdate();
}
function getOptionsLink(): string {
let optionsLinkUrl =
window.location.origin + '/' + window.location.hash + '?';
if (updateProposalTitles)
optionsLinkUrl = optionsLinkUrl = 'proposalTitles=1&';
NETWORKS.map((network, i) => {
const networkName = network.name;
if (localConfig[networkName + '_toBlock'])
optionsLinkUrl =
optionsLinkUrl +
networkName +
'_toBlock=' +
localConfig[networkName + '_toBlock'] +
'&';
if (localConfig[networkName + '_targetHash'])
optionsLinkUrl =
optionsLinkUrl +
networkName +
'_targetHash=' +
localConfig[networkName + '_targetHash'] +
'&';
if (resetCache[networkName])
optionsLinkUrl = optionsLinkUrl + networkName + '_reset=1&';
});
optionsLinkUrl = optionsLinkUrl.slice(0, -1);
return optionsLinkUrl;
}
return buildingCacheState === 1 ? (
<LoadingBox>
<div className="loader">
{' '}
<PulsingIcon size={80} inactive={false} />
<LoadingProgressText>
{notificationStore.globalMessage}
</LoadingProgressText>
</div>
</LoadingBox>
) : (
<Box>
<FormContainer>
{NETWORKS.map((network, i) => {
const networkName = network.name;
return (
networkName !== 'localhost' && (
<div key={`networkOptions${i}`}>
<RowAlignedLeft>
{' '}
<strong>{toCamelCaseString(networkName)}</strong>{' '}
</RowAlignedLeft>
<RowAlignedLeft>
<FormLabel>Block:</FormLabel>
<InputBox
type="text"
onChange={event =>
onApiKeyValueChange(
event.target.value,
networkName + '_toBlock'
)
}
value={localConfig[networkName + '_toBlock']}
style={{ width: '100px' }}
></InputBox>
<FormLabel>RPC:</FormLabel>
<InputBox
type="text"
onChange={event =>
onApiKeyValueChange(
event.target.value,
networkName + '_rpcURL'
)
}
value={localConfig[networkName + '_rpcURL']}
style={{ width: '100%' }}
></InputBox>
<FormLabel>Reset</FormLabel>
<InputBox
type="checkbox"
checked={resetCache[networkName]}
onChange={() => {
resetCache[networkName] = !resetCache[networkName];
setResetCache(resetCache);
forceUpdate();
}}
></InputBox>
</RowAlignedLeft>
<RowAlignedLeft>
<FormLabel>Target Config Hash:</FormLabel>
<InputBox
type="text"
onChange={event =>
onApiKeyValueChange(
event.target.value,
networkName + '_targetHash'
)
}
value={localConfig[networkName + '_targetHash']}
style={{ width: '400px' }}
></InputBox>
{updatedCacheHash.configs[networkName] && (
<div>
<Button
onClick={() =>
uploadToIPFS(
JSON.stringify(
updatedCacheHash.configs[networkName],
null,
2
)
)
}
>
<FiUpload></FiUpload> Config
</Button>
<Button
onClick={() =>
uploadToIPFS(
JSON.stringify(
updatedCacheHash.caches[networkName],
null,
2
)
)
}
>
<FiUpload></FiUpload> Cache
</Button>
</div>
)}
</RowAlignedLeft>
{updatedCacheHash.configs[networkName] && (
<RowAlignedLeft>
Received Config Hash:{' '}
{updatedCacheHash.configHashes[networkName]}
{' '}
<FormLabel>
{updatedCacheHash.configHashes[networkName] ==
localConfig[networkName + '_targetHash'] ? (
<FiCheckCircle />
) : (
<FiX />
)}
</FormLabel>
</RowAlignedLeft>
)}
</div>
)
);
})}
</FormContainer>
<Row style={{ justifyContent: 'left' }}>
<FormLabel>Update Proposal Titles</FormLabel>
<InputBox
type="checkbox"
checked={updateProposalTitles}
onChange={() => setUpdateProposalTitles(!updateProposalTitles)}
></InputBox>
</Row>
{buildingCacheState === 2 && (
<Row>
<Button onClick={downloadAll}>
{' '}
<FiDownload></FiDownload> Download All
</Button>
</Row>
)}
<Row>
<Button onClick={runCacheScript}>Build Cache</Button>
<Button onClick={resetCacheOptions}>Reset Options</Button>
<CopyButton>
<Copy toCopy={getOptionsLink()}>Build Link</Copy>
</CopyButton>
</Row>
</Box>
);
})
Example #16
Source File: BottomNav.tsx From meshtastic-web with GNU General Public License v3.0 | 4 votes |
BottomNav = (): JSX.Element => {
const [showVersionInfo, setShowVersionInfo] = useState(false);
const dispatch = useAppDispatch();
const meshtasticState = useAppSelector((state) => state.meshtastic);
const appState = useAppSelector((state) => state.app);
const primaryChannelSettings = useAppSelector(
(state) => state.meshtastic.radio.channels,
).find((channel) => channel.role === Protobuf.Channel_Role.PRIMARY)?.settings;
const metrics =
meshtasticState.nodes[meshtasticState.radio.hardware.myNodeNum]?.metrics;
return (
<div className="z-20 flex justify-between divide-x divide-gray-400 border-t border-gray-400 bg-white dark:divide-gray-600 dark:border-gray-600 dark:bg-secondaryDark">
<BottomNavItem tooltip="Meshtastic WebUI">
<img
title="Logo"
className="my-auto w-5"
src={appState.darkMode ? '/Logo_White.svg' : '/Logo_Black.svg'}
/>
</BottomNavItem>
<BottomNavItem
tooltip="Connection Status"
onClick={(): void => {
dispatch(openConnectionModal());
}}
className={
[
Types.DeviceStatusEnum.DEVICE_CONNECTED,
Types.DeviceStatusEnum.DEVICE_CONFIGURED,
].includes(meshtasticState.deviceStatus)
? 'bg-primary dark:bg-primary'
: [
Types.DeviceStatusEnum.DEVICE_CONNECTING,
Types.DeviceStatusEnum.DEVICE_RECONNECTING,
Types.DeviceStatusEnum.DEVICE_CONFIGURING,
].includes(meshtasticState.deviceStatus)
? 'bg-yellow-400 dark:bg-yellow-400'
: ''
}
>
{appState.connType === connType.BLE ? (
<FiBluetooth className="h-4" />
) : appState.connType === connType.SERIAL ? (
<FiCpu className="h-4" />
) : (
<FiWifi className="h-4" />
)}
<div className="truncate text-xs font-medium">
{meshtasticState.nodes.find(
(node) =>
node.data.num === meshtasticState.radio.hardware.myNodeNum,
)?.data.user?.longName ?? 'Disconnected'}
</div>
</BottomNavItem>
<BottomNavItem tooltip="Battery Level">
{!metrics?.batteryLevel ? (
<IoBatteryDeadOutline className="h-4" />
) : metrics?.batteryLevel > 50 ? (
<IoBatteryFullOutline className="h-4" />
) : metrics?.batteryLevel > 0 ? (
<IoBatteryFullOutline className="h-4" />
) : (
<IoBatteryChargingOutline className="h-4" />
)}
<div className="truncate text-xs font-medium">
{metrics?.batteryLevel
? `${metrics?.batteryLevel}% - ${metrics?.voltage}v`
: 'No Battery'}
</div>
</BottomNavItem>
<BottomNavItem tooltip="Network Utilization">
<div className="m-auto h-3 w-3 rounded-full bg-primary" />
<div className="truncate text-xs font-medium">
{`${metrics?.airUtilTx ?? 0}% - Air`} |
</div>
<div
className={`m-auto h-3 w-3 rounded-full ${
!metrics?.channelUtilization
? 'bg-primary'
: metrics?.channelUtilization > 50
? 'bg-red-400'
: metrics?.channelUtilization > 24
? 'bg-yellow-400'
: 'bg-primary'
}`}
/>
<div className="truncate text-xs font-medium">
{`${metrics?.channelUtilization ?? 0}% - Ch`}
</div>
</BottomNavItem>
<BottomNavItem tooltip="MQTT Status">
{primaryChannelSettings?.uplinkEnabled &&
primaryChannelSettings?.downlinkEnabled &&
!meshtasticState.radio.moduleConfig.mqtt.disabled ? (
<RiArrowUpDownLine className="h-4" />
) : primaryChannelSettings?.uplinkEnabled &&
!meshtasticState.radio.moduleConfig.mqtt.disabled ? (
<RiArrowUpLine className="h-4" />
) : primaryChannelSettings?.downlinkEnabled &&
!meshtasticState.radio.moduleConfig.mqtt.disabled ? (
<RiArrowDownLine className="h-4" />
) : (
<FiX className="h-4" />
)}
</BottomNavItem>
<div className="flex-grow">
<BottomNavItem
onClick={(): void => {
dispatch(toggleMobileNav());
}}
className="md:hidden"
>
{appState.mobileNavOpen ? (
<FiX className="m-auto h-4" />
) : (
<FiMenu className="m-auto h-4" />
)}
</BottomNavItem>
</div>
<BottomNavItem
tooltip={
appState.updateAvaliable ? 'Update Avaliable' : 'Current Commit'
}
onClick={(): void => {
setShowVersionInfo(true);
}}
className={appState.updateAvaliable ? 'animate-pulse' : ''}
>
{appState.updateAvaliable ? (
<MdUpgrade className="h-4" />
) : (
<FiGitBranch className="h-4" />
)}
<p className="text-xs opacity-60">{process.env.COMMIT_HASH}</p>
</BottomNavItem>
<BottomNavItem
tooltip="Toggle Theme"
onClick={(): void => {
dispatch(setDarkModeEnabled(!appState.darkMode));
}}
>
{appState.darkMode ? (
<FiSun className="h-4" />
) : (
<FiMoon className="h-4" />
)}
</BottomNavItem>
<VersionInfo
modalOpen={showVersionInfo}
onClose={(): void => {
setShowVersionInfo(false);
}}
/>
</div>
);
}
Example #17
Source File: PermissionsInformation.tsx From dxvote with GNU Affero General Public License v3.0 | 4 votes |
PermissionsInformation = observer(() => {
const {
context: { daoStore, configStore, providerStore },
} = useContext();
const web3 = providerStore.getActiveWeb3React().library;
const schemes = daoStore.getAllSchemes();
const rawPermissions = daoStore.daoCache.callPermissions;
const networkContracts = configStore.getNetworkContracts();
const tokens = configStore.getTokensOfNetwork();
const recommendedCalls = configStore.getRecommendedCalls();
let addressesNames = {};
let functionNames = {};
addressesNames[ZERO_ADDRESS] =
NETWORK_ASSET_SYMBOL[configStore.getActiveChainName()];
addressesNames[ANY_ADDRESS] = 'Any Address';
addressesNames[networkContracts.avatar] = 'Avatar';
addressesNames[networkContracts.controller] = 'Controller';
for (const votingMachineAddress in networkContracts.votingMachines) {
addressesNames[votingMachineAddress] =
networkContracts.votingMachines[votingMachineAddress].type;
}
functionNames[
web3.eth.abi.encodeFunctionSignature('mintTokens(uint256,address,address)')
] = 'mintTokens(uint256,address,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature('unregisterSelf(address)')
] = 'unregisterSelf(address)';
functionNames[
web3.eth.abi.encodeFunctionSignature(
'addGlobalConstraint(address,bytes32,address)'
)
] = 'addGlobalConstraint(address,bytes32,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature(
'removeGlobalConstraint(address,address)'
)
] = 'removeGlobalConstraint(address,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature('upgradeController(address,address)')
] = 'upgradeController(address,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature('sendEther(uint256,address,address)')
] = 'sendEther(uint256,address,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature(
'externalTokenTransfer(address,address,uint256,address)'
)
] = 'externalTokenTransfer(address,address,uint256,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature(
'externalTokenTransferFrom(address,address,address,uint256,address)'
)
] = 'externalTokenTransferFrom(address,address,address,uint256,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature(
'externalTokenApproval(address,address,uint256,address)'
)
] = 'externalTokenApproval(address,address,uint256,address)';
functionNames[
web3.eth.abi.encodeFunctionSignature('metaData(string,address)')
] = 'metaData(string,address)';
functionNames[ERC20_TRANSFER_SIGNATURE] = 'ERC20 Transfer';
functionNames[ERC20_APPROVE_SIGNATURE] = 'ERC20 Approve';
recommendedCalls.map(recommendedCall => {
functionNames[
web3.eth.abi.encodeFunctionSignature(recommendedCall.functionName)
] = recommendedCall.functionName;
});
schemes.map(scheme => {
addressesNames[scheme.address] = scheme.name;
});
tokens.map(token => {
addressesNames[token.address] = token.symbol;
});
const permissions = [];
for (const assetAddress in rawPermissions) {
for (const fromAddress in rawPermissions[assetAddress]) {
for (const toAddress in rawPermissions[assetAddress][fromAddress]) {
for (const functionSignature in rawPermissions[assetAddress][
fromAddress
][toAddress]) {
const value =
rawPermissions[assetAddress][fromAddress][toAddress][
functionSignature
].value.toString();
permissions.push({
asset: addressesNames[assetAddress] || assetAddress,
from: addressesNames[fromAddress] || fromAddress,
to: addressesNames[toAddress] || toAddress,
functionSignature:
functionSignature === ANY_FUNC_SIGNATURE
? 'Any Function'
: functionSignature,
value:
value ===
'115792089237316195423570985008687907853269984665640564039457584007913129639935'
? 'ANY Value'
: value,
fromTime:
rawPermissions[assetAddress][fromAddress][toAddress][
functionSignature
].fromTime,
});
}
}
}
}
return (
<PermissionsTable>
<TableHeader>
<HeaderCell>Asset</HeaderCell>
<HeaderCell>From</HeaderCell>
<HeaderCell>To</HeaderCell>
<HeaderCell>Function</HeaderCell>
<HeaderCell>Value</HeaderCell>
<HeaderCell>From Time</HeaderCell>
</TableHeader>
<TableBody>
{permissions.map((permission, i) => (
<TableRow key={`permission${i}`}>
<DataCell>{permission.asset}</DataCell>
<DataCell>{permission.from}</DataCell>
<DataCell>{permission.to}</DataCell>
<DataCell>
{functionNames[permission.functionSignature] ||
permission.functionSignature}
</DataCell>
<DataCell>{permission.value}</DataCell>
<DataCell>
{permission.fromTime === 0 ? (
<FiX />
) : (
timestampToDate(bnum(permission.fromTime))
)}
</DataCell>
</TableRow>
))}
</TableBody>
</PermissionsTable>
);
})
Example #18
Source File: TransactionModal.tsx From dxvote with GNU Affero General Public License v3.0 | 4 votes |
TransactionModal: React.FC<TransactionModalProps> = ({
message,
transactionHash,
txCancelled,
onCancel,
}) => {
const { chainId } = useWeb3React();
const modalView = useMemo<TransactionModalView>(() => {
if (txCancelled) {
return TransactionModalView.Reject;
} else if (transactionHash) {
return TransactionModalView.Submit;
} else {
return TransactionModalView.Confirm;
}
}, [txCancelled, transactionHash]);
const [header, children, footerText] = useMemo(() => {
let header: JSX.Element, children: JSX.Element, footerText: string;
switch (modalView) {
case TransactionModalView.Confirm:
header = (
<Header>
<PendingCircle height="86px" width="86px" color="black" />
</Header>
);
children = (
<Flex>
<Container>
<ContainerText variant="bold">
Waiting For Confirmation
</ContainerText>
<ContainerText variant="medium">{message}</ContainerText>
</Container>
<ContainerText variant="medium" color="grey">
Confirm this Transaction in your Wallet
</ContainerText>
</Flex>
);
break;
case TransactionModalView.Submit:
header = (
<Header>
<Circle>
<AiOutlineArrowUp size={40} />
</Circle>
</Header>
);
const networkName = getChains().find(
chain => chain.id === chainId
).name;
children = (
<Flex>
<ContainerText variant="bold">Transaction Submitted</ContainerText>
<Container>
<ContainerText
as="a"
variant="regular"
color="grey"
href={getBlockchainLink(transactionHash, networkName)}
target="_blank"
>
View on Block Explorer
</ContainerText>
</Container>
</Flex>
);
footerText = 'Close';
break;
case TransactionModalView.Reject:
header = (
<Header>
<Circle>
<FiX size={40} />
</Circle>
</Header>
);
children = (
<Flex>
<ContainerText variant="bold">Transaction Rejected</ContainerText>
</Flex>
);
footerText = 'Dismiss';
break;
}
return [header, children, footerText];
}, [modalView, chainId, message, transactionHash]);
return (
<Modal
isOpen={!!message}
onDismiss={onCancel}
children={children}
contentHeader={header}
cross
hideHeader
showSecondaryHeader
onCancel={onCancel}
maxWidth={300}
cancelText={footerText}
zIndex={1000}
/>
);
}
Example #19
Source File: ERC20TransferEditor.tsx From dxvote with GNU Affero General Public License v3.0 | 4 votes |
Transfer: React.FC<ActionEditorProps> = ({ decodedCall, updateCall }) => {
const [isTokenPickerOpen, setIsTokenPickerOpen] = useState(false);
const { chainId } = useWeb3React();
// parse transfer state from calls
const parsedData = useMemo<TransferState>(() => {
if (!decodedCall) return null;
return {
source: decodedCall.from,
tokenAddress: decodedCall.to,
amount: decodedCall.args._value,
destination: decodedCall.args._to,
};
}, [decodedCall]);
const validations = useMemo(() => {
return {
tokenAddress: utils.isAddress(parsedData?.tokenAddress),
amount: BigNumber.isBigNumber(parsedData?.amount),
destination: utils.isAddress(parsedData?.destination),
};
}, [parsedData]);
// Get token details from the token address
const { tokens } = useTokenList(chainId);
const token = useMemo(() => {
if (!parsedData?.tokenAddress || !tokens) return null;
return tokens.find(({ address }) => address === parsedData.tokenAddress);
}, [tokens, parsedData]);
const { data: tokenInfo } = useERC20Info(parsedData?.tokenAddress);
const roundedBalance = useBigNumberToNumber(
parsedData?.amount,
tokenInfo?.decimals,
10
);
const { imageUrl: destinationAvatarUrl } = useENSAvatar(
parsedData?.destination,
MAINNET_ID
);
const setTransferAddress = (walletAddress: string) => {
updateCall({
...decodedCall,
args: {
...decodedCall.args,
_to: walletAddress,
},
});
};
const setToken = (tokenAddress: string) => {
updateCall({
...decodedCall,
to: tokenAddress,
});
};
const setAmount = (value: string) => {
const amount = value
? utils.parseUnits(value, tokenInfo?.decimals || 18)
: null;
updateCall({
...decodedCall,
args: {
...decodedCall.args,
_value: amount,
},
});
};
return (
<div>
<Control>
<ControlLabel>Recipient</ControlLabel>
<ControlRow>
<Input
value={parsedData.destination || ''}
icon={
<div>
{validations.destination && (
<Avatar
src={destinationAvatarUrl}
defaultSeed={parsedData.destination}
size={24}
/>
)}
</div>
}
iconRight={
parsedData?.destination ? (
<ClickableIcon onClick={() => setTransferAddress('')}>
<FiX size={18} />
</ClickableIcon>
) : null
}
placeholder="Ethereum address"
onChange={e => setTransferAddress(e.target.value)}
/>
</ControlRow>
</Control>
<ControlRow>
<Control>
<ControlLabel>Amount</ControlLabel>
<ControlRow>
<TransferAmountInput
value={roundedBalance}
onUserInput={setAmount}
/>
</ControlRow>
</Control>
<Spacer />
<Control>
<ControlLabel>Asset</ControlLabel>
<ControlRow onClick={() => setIsTokenPickerOpen(true)}>
<Input
value={tokenInfo?.symbol || ''}
placeholder="Token"
icon={
<div>
{parsedData?.tokenAddress && (
<Avatar
src={resolveUri(token?.logoURI)}
defaultSeed={parsedData?.tokenAddress}
size={18}
/>
)}
</div>
}
iconRight={<FiChevronDown size={24} />}
readOnly
/>
</ControlRow>
</Control>
</ControlRow>
<TokenPicker
walletAddress={parsedData?.source || ''}
isOpen={isTokenPickerOpen}
onClose={() => setIsTokenPickerOpen(false)}
onSelect={tokenAddress => {
setToken(tokenAddress);
setIsTokenPickerOpen(false);
}}
/>
</div>
);
}