@fortawesome/free-solid-svg-icons#faArrowDown JavaScript Examples
The following examples show how to use
@fortawesome/free-solid-svg-icons#faArrowDown.
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: Tables.js From volt-react-dashboard with MIT License | 5 votes |
PageVisitsTable = () => {
const TableRow = (props) => {
const { pageName, views, returnValue, bounceRate } = props;
const bounceIcon = bounceRate < 0 ? faArrowDown : faArrowUp;
const bounceTxtColor = bounceRate < 0 ? "text-danger" : "text-success";
return (
<tr>
<th scope="row">{pageName}</th>
<td>{views}</td>
<td>${returnValue}</td>
<td>
<FontAwesomeIcon icon={bounceIcon} className={`${bounceTxtColor} me-3`} />
{Math.abs(bounceRate)}%
</td>
</tr>
);
};
return (
<Card border="light" className="shadow-sm">
<Card.Header>
<Row className="align-items-center">
<Col>
<h5>Page visits</h5>
</Col>
<Col className="text-end">
<Button variant="secondary" size="sm">See all</Button>
</Col>
</Row>
</Card.Header>
<Table responsive className="align-items-center table-flush">
<thead className="thead-light">
<tr>
<th scope="col">Page name</th>
<th scope="col">Page Views</th>
<th scope="col">Page Value</th>
<th scope="col">Bounce rate</th>
</tr>
</thead>
<tbody>
{pageVisits.map(pv => <TableRow key={`page-visit-${pv.id}`} {...pv} />)}
</tbody>
</Table>
</Card>
);
}
Example #2
Source File: previewlayout.js From ActiveLearningStudio-react-client with GNU Affero General Public License v3.0 | 4 votes |
PreviewLayout = (props) => {
const { changeScreenHandler } = props;
return (
<div className="preview-layout-form">
{/* <div className="preview-layout-back">
<Link
className="back-link"
onClick={() => changeScreenHandler("addactivity")}
>
<FontAwesomeIcon icon="chevron-left" className="icon-link" />
Back
</Link>
</div> */}
<div className="preview-layout-tabs">
<Tabs text="1. Select an activity" tabActive={true} />
<Tabs text="2. Add activities to Layout" className="ml-10 mt-10" tabActive={true} />
<Tabs text="3. Preview Activity" className="ml-10" tabActive={true} />
</div>
<div className="preview-layout-title-select">
<div className="preview-layout-title">
<HeadingTwo text="Interactive Video" color="#084892" />
</div>
{/* <div className="preview-layout-change-layout">
<select>
<option>Change Layout</option>
<option>Interactive video</option>
<option>Column layout</option>
<option>Interactive book</option>
<option>Course presentation</option>
<option>Quiz</option>
<option>Single activity</option>
</select>
</div> */}
</div>
<div className="preview-layout-card-project">
<div className="preview-layout-dialogcard">
<div className="dialogcard-subtitle">
<HeadingThree text="Activity title" color="#084892" />
</div>
<div>
<HeadingText text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam." />
</div>
<div className="preview-layout-panel">
<div className="layout-panel">
<HeadingThree text="First panel " color="#084892" />
<FontAwesomeIcon icon="chevron-down" color="#084892" />
</div>
<div className="layout-panel mt-8">
<HeadingThree text="Second panel " color="#084892" />
<FontAwesomeIcon icon="chevron-down" color="#084892" />
</div>
</div>
<div className="preview-layout-footer">
<div className="footer-dowload">
<p>
<FontAwesomeIcon icon={faArrowDown} /> Download
</p>
</div>
<div>
<p>
<FontAwesomeIcon icon={faAngleLeft} /> <FontAwesomeIcon icon={faAngleRight} />
Embed
</p>
</div>
<div>
<img src={ExplanatoryH5P} />
</div>
</div>
{/* <div className="dialogcard-subtitle">
<HeadingText
text="Dialog Card"
color="#084892"
className="subtitle-text"
/>
</div>
<div className="dialogcard-title">
<HeadingTwo
text="Activity Title"
color="#084892"
className="title-heading"
/>
<HeadingThree
text="Heading"
color="#084892"
className="sub-heading"
/>
</div>
<div className="detail-dialogcard">
<div className="card-actvity">
<img src={CarDImage} alt="" />
<div>
<FontAwesomeIcon
icon="volume-up"
className="card-actvity-icon"
/>
</div>
<HeadingThree
text="Activity Title"
className="card-actvity-title"
/>
<Buttons
icon="sync-alt"
text="Turn"
primary={true}
width="96px"
height="35px"
className="card-actvity-btn"
/>
</div>
</div>
<div className="card-pagination">
<div className="pagination-text">
<HeadingText text="Card 1 of 5" />
</div>
<div className="pagination-icon">
<FontAwesomeIcon icon="angle-right" className="icon-next" />
</div>
</div> */}
</div>
<div className="preview-layout-project">
<div className="project-title-link">
<div className="project-title">
<HeadingTwo text="Project: " color="#084892" className="project-heading" />
<HeadingText text="Project title here" color="#515151" />
<HeadingTwo text="Playlist:" color="#084892" className="playlist-heading" />
<HeadingText text="Playlist name here" color="#515151" />
</div>
<div className="project-link">
<Link className="get-link">
{/* <FontAwesomeIcon icon="link" className="icon-link" />*/}
Get link
</Link>
</div>
</div>
<div className="dialog-card-box">
<img src={DialogCardImage} alt="" />
<HeadingText text="Dialog Cards" color="#084892" className="ml-15" />
</div>
{/* <div className="add-more-activity">
<div className="more-activity-icon">
<FontAwesomeIcon icon="link" className="icon-link" />
</div>
<Link className="more-activity-link" to="/">
Add More Activity
</Link>
</div> */}
<div className="project-link-button">
<Buttons text="Back to Editor" primary={true} width="126px" height="43px" hover={true} onClick={() => changeScreenHandler('addactivity')} />
<Buttons text="Finish Layout" secondary={true} width="126px" height="43px" hover={true} onClick={() => changeScreenHandler('')} />
</div>
</div>
</div>
</div>
);
}
Example #3
Source File: Popup.js From gophie-web with MIT License | 4 votes |
render() {
const { server } = this.props;
return (
<Modal
show={this.props.show}
onHide={() => this.props.onHide()}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
dialogClassName="dialog-theme"
data-tour="my-fifth-step"
centered
>
<Modal.Body className="gophie-modal">
<section className="gophie-modal__img">
<img
src={
this.props.movie.cover_photo_link === ""
? "No image"
: this.props.movie.cover_photo_link
}
alt={this.props.movie.name}
/>
{/* Video Stream Play Icon */}
{this.state.play ? (
<a
id="stop-video"
className="video-stop-button"
href="/"
onClick={this.handleStopRequest.bind(this)}
>
<span></span>{" "}
</a>
) : (
<div>
{greekFromEnglish(server) === "Server2" ? null : (
<a
id="play-video"
className="video-play-button"
href="/"
onClick={this.handlePlayRequest.bind(this)}
>
<span> </span>{" "}
</a>
)}
</div>
)}
{/* Video Stream Play Icon */}
</section>
<section className="gophie-modal__body">
<Modal.Header className="gophie-modal__body--header" closeButton>
<Modal.Title id="contained-modal-title-vcenter">
{this.props.movie.name}
</Modal.Title>
</Modal.Header>
{this.state.play ? (
<div>
<div className="player-wrapper">
<ReactPlayer
url={this.props.movie.download_link}
className="react-player"
playing
playsinline
pip
controls
width="100%"
height="90%"
/>
</div>
{greekFromEnglish(this.props.movie.engine) === "Alpha" ? (
<div className="player-error-alert">
<p className="player-error-message">
Streaming from alpha is problematic, suggest{" "}
<a
className="gophie-link"
href={this.props.movie.download_link}
target="_blank"
rel="noopener noreferrer"
>
downloading
</a>{" "}
instead
</p>
</div>
) : null}
{isIOS ? (
<div className="player-error-alert">
<p className="player-error-message">
{" "}
iOS 10+ users might have to disable{" "}
<i>
<em>Low Power Mode</em>
</i>{" "}
to stream
</p>
</div>
) : null}
</div>
) : (
<section className="gophie-modal__body--body">
<div className="gophie-modal-rating-container">
<div
className="gophie-modal-rating-container__average"
data-tour="my-seventh-step"
>
<div className="gophie-modal-rating-container__average--container">
<div className="gophie-modal-rating-container__average--container-item-1">
<p>
{this.state.ratings.average_ratings
? Math.round(
this.state.ratings.average_ratings * 10
) / 10
: 0}
</p>
<p>/5</p>
</div>
<p className="em-rate">
<span className="em-span">by</span>
{this.state.ratings.by
? Math.round(this.state.ratings.by)
: 0}
</p>
</div>
</div>
<div
className="gophie-modal-rating-container__rate"
data-tour="my-sixth-step"
>
<p>Rate Movie</p>
<Rating
value={this.state.ip_rating}
max={5}
onChange={(value) => this.rateMovie(value)}
/>
</div>
</div>
<div className="gophie-modal__body--description scollable-container">
{this.props.movie.description === ""
? "Seems like the description for this movie is missing"
: this.props.movie.description}
</div>
<div>
<div></div>
{this.props.movie.name !== "AnimeOut" ? null : (
<div>
<div className="d-flex justify-content-between align-items-center w-100 mt-3">
<div>Episodes</div>
<FontAwesomeIcon icon={faArrowDown} />
</div>
<div className="scollable-container d-flex flex-column">
{this.state.episodeLink}
</div>
</div>
)}
</div>
</section>
)}
</section>
</Modal.Body>
</Modal>
);
}
Example #4
Source File: index.js From Website with Apache License 2.0 | 4 votes |
export default function Downloads() {
const [releases, setReleases] = useState([]);
useEffect(() => {
async function getReleases() {
const response = await fetch(
"https://api.github.com/repos/PGMDev/PGM/releases"
);
return setReleases(await response.json());
}
getReleases();
}, []);
return (
<Layout title="Downloads">
<div className={classnames("container", styles.downloads_container)}>
<h1 className={styles.downloads_title}>Downloads</h1>
{releases.length === 0 ? (
<div className={classnames("hero", styles.spinner_hero)}>
<div className={styles.lds_ripple}>
<div></div>
<div></div>
</div>
</div>
) : (
<div
className={classnames(
"hero",
styles.downloads_hero,
styles.appearing
)}
>
<div className="container row">
<div className="col">
<div className="row">
<img src="/img/shield.png" className={styles.pgm_logo} />
<div className={styles.pgm}>
<h1>PGM {releases[0].name}</h1>
<p>
<label>
{" "}
{format(
new Date(releases[0].published_at),
"LLLL do, yyyy"
)}{" "}
</label>
</p>
<a href={releases[0].html_url}>
Changelog <FontAwesomeIcon icon={faAngleRight} />
</a>
</div>
</div>
<div className={styles.description}>
<p>
Minecraft multiplayer game-server suite for managing PvP
matches across various gamemodes
</p>
</div>
</div>
<div className={classnames("col col--4", styles.col_border)}>
<h2>Download PGM</h2>
<p>
PvP Game Manager (PGM) is a plugin that manages running and
instancing multiple PvP maps across various gamemodes for
Minecraft multiplayer.
</p>
<a
className={classnames(
"button button--primary",
styles.download_button
)}
href={releases[0].assets[0].browser_download_url}
>
Download <FontAwesomeIcon icon={faArrowDown} />
</a>
</div>
<div className={classnames("col col--4", styles.col_margin_left)}>
<h2>Download SportPaper</h2>
<p>
SportPaper is a Minecraft server jar based on Paper 1.8 tuned
for maximum performance and high intensity PvP. It is
mandatory and should run alongside PGM.
</p>
<a
className={classnames(
"button button--primary",
styles.download_button
)}
href={releases[0].assets[1].browser_download_url}
>
Download <FontAwesomeIcon icon={faArrowDown} />
</a>
</div>
</div>
</div>
)}
<div className={styles.others}>
<h2 style={{ marginBottom: "-15px" }}>Other Resources</h2>
<div className="row">
<div className={classnames("col col--6", styles.column)}>
<div className={classnames("hero", styles.others_hero)}>
<div className="col">
<div className="row">
<div className="col col--6">
<div className="row">
<h1 className={styles.others_icon}>
<FontAwesomeIcon icon={faCalendarAlt} />
</h1>
<div className={styles.others_header}>
<h2>Events</h2>
<a href="https://github.com/PGMDev/Events/">
<label>GitHub</label>
</a>
</div>
</div>
</div>
<div className="col col--6">
<a
className={classnames(
"button button--primary",
styles.others_button
)}
href="https://github.com/PGMDev/Events/releases/latest"
>
Download <FontAwesomeIcon icon={faArrowDown} />
</a>
</div>
</div>
<div className={styles.others_description}>
<p>
Events is the official PGM plugin for managing PvP matches
in a competitive setting. Upon joining or cycling, all
team members are forced onto their respective teams.
</p>
</div>
</div>
</div>
</div>
<div className={classnames("col col--6", styles.column)}>
<div className={classnames("hero", styles.others_hero)}>
<div className="col">
<div className="row">
<div className="col col--6">
<div className="row">
<h1 className={styles.others_icon}>
<FontAwesomeIcon icon={faUsers} />
</h1>
<div className={styles.others_header}>
<h2>Community</h2>
<a href="https://github.com/PGMDev/Community/">
<label>GitHub</label>
</a>
</div>
</div>
</div>
<div className="col col--6">
<button
className={classnames(
"button disabled button--primary",
styles.others_button
)}
>
Coming Soon <FontAwesomeIcon icon={faArrowDown} />
</button>
</div>
</div>
<div className={styles.others_description}>
<p>
Community is a standalone plugin for managing PGM servers.
It includes various PGM features, such as punishments,
moderation, freezing and other aspects.
</p>
</div>
</div>
</div>
</div>
</div>
<hr style={{ marginTop: "40px", marginBottom: "10px" }} />
<div className="row">
<div className={classnames("col col--6", styles.column)}>
<div className={classnames("hero", styles.others_hero)}>
<div className="col">
<div className="row">
<div className="col col--6">
<div className="row">
<h1 className={styles.others_icon}>
<FontAwesomeIcon icon={faFolderOpen} />
</h1>
<div className={styles.others_header}>
<h2>ResourcePile</h2>
<a href="https://github.com/MCResourcePile">
<label>GitHub</label>
</a>
</div>
</div>
</div>
<div className="col col--6">
<a
className={classnames(
"button button--primary",
styles.others_button
)}
href="https://mcresourcepile.github.io"
>
Visit <FontAwesomeIcon icon={faFolderOpen} />
</a>
</div>
</div>
<div className={styles.others_description}>
<p>
ResourcePile is a community project which aims to provide
various collections of resources, such as maps or
statistics, for users with backgrounds in Overcast and
similar networks.
</p>
</div>
</div>
</div>
</div>
<div className={classnames("col col--6", styles.column)}>
<div className={classnames("hero", styles.others_hero)}>
<div className="col">
<div className="row">
<div className="col col--6">
<div className="row">
<h1 className={styles.others_icon}>
<FontAwesomeIcon icon={faCompass} />
</h1>
<div className={styles.others_header}>
<h2>PGM Tracker</h2>
<a href="https://pgm.fyi">
<label>Website</label>
</a>
</div>
</div>
</div>
<div className="col col--6">
<a
className={classnames(
"button button--primary",
styles.others_button
)}
href="https://pgm.fyi"
>
Visit <FontAwesomeIcon icon={faCompass} />
</a>
</div>
</div>
<div className={styles.others_description}>
<p>
PGM Tracker is a community tool made by{" "}
<a href="https://github.com/applenick">applenick</a> that
tracks public PGM servers. Take a look at it, play a
variety of Minecraft PvP maps and get involved with
development!
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</Layout>
);
}
Example #5
Source File: index.jsx From loopring-swap with GNU General Public License v3.0 | 4 votes |
Swapper = ({ onConnectWalletClick }) => {
const { formatNumber } = useIntl();
const dispatch = useDispatch();
const {
loopringAccount,
loopringExchange,
loopringWallet,
supportedTokens,
loadingSupportedTokens,
loadingBalances,
supportedMarkets,
balances,
loggedIn,
swapData,
loadingSwapData,
loadingSwapSubmission,
} = useSelector((state) => ({
loopringAccount: state.loopring.account,
loopringExchange: state.loopring.exchange,
loopringWallet: state.loopring.wallet,
supportedTokens: state.loopring.supportedTokens.data,
loadingSupportedTokens: !!state.loopring.supportedTokens.loadings,
loadingBalances: !!state.loopring.balances.loadings,
supportedMarkets: state.loopring.supportedMarkets.data,
balances: state.loopring.balances.data,
loggedIn: !!state.loopring.account,
swapData: state.loopring.swap.data,
loadingSwapData: !!state.loopring.swap.loadings,
loadingSwapSubmission: !!state.loopring.swapSubmission.loadings,
}));
const [fromToken, setFromToken] = useState(null);
const [fromAmount, setFromAmount] = useState("");
const [liquidityError, setLiquidityError] = useState(null);
const [balanceError, setBalanceError] = useState(null);
const [lessThanMinimumOrderError, setLessThanMinimumOrderError] = useState(
null
);
const [moreThanMaximumOrderError, setMoreThanMaximumOrderError] = useState(
null
);
const [toToken, setToToken] = useState(null);
const [toAmount, setToAmount] = useState("");
const [feeAmount, setFeeAmount] = useState("");
const [filteredToTokens, setFilteredToTokens] = useState([]);
const [compatibleMarkets, setCompatibleMarkets] = useState([]);
const [changingToAmount, setChangingToAmount] = useState(false);
const [changingFromAmount, setChangingFromAmount] = useState(false);
const [selling, setSelling] = useState(false);
const [flippedPriceNotation, setFlippedPriceNotation] = useState(false);
const [debouncedGetSwapData] = useDebouncedCallback(
(
wallet,
account,
fromToken,
toToken,
fromAmount,
supportedTokens,
selling
) => {
dispatch(
getSwapData(
wallet,
account,
fromToken,
toToken,
fromAmount,
supportedTokens,
selling
)
);
},
500
);
useEffect(() => {
if (loggedIn) {
setFromAmount("");
setToAmount("");
dispatch(resetSwapData());
setLiquidityError(false);
setBalanceError(false);
setLessThanMinimumOrderError(false);
setMoreThanMaximumOrderError(false);
}
}, [dispatch, loggedIn]);
// set ether as the default "from" token
useEffect(() => {
if (supportedTokens && supportedTokens.length > 0 && !fromToken) {
setFromToken(
supportedTokens.find((token) => token.symbol === "ETH")
);
}
}, [fromToken, supportedTokens]);
// on "from" token change, find out the compatible markets
useEffect(() => {
if (supportedMarkets && supportedMarkets.length > 0 && fromToken) {
setCompatibleMarkets(
supportedMarkets.filter(
(market) =>
market.quoteTokenId === fromToken.tokenId ||
market.baseTokenId === fromToken.tokenId
)
);
}
}, [fromToken, supportedMarkets]);
// on "from" token change, we need to find the compatible "to" tokens based on available markets.
// Plus, we reset the currently selected "to" token if it's not compatible with the current "from" one.
useEffect(() => {
if (supportedMarkets && supportedMarkets.length > 0 && fromToken) {
const filteredToTokens = supportedTokens.filter(
(token) =>
token.tokenId !== fromToken.tokenId &&
compatibleMarkets.find(
(market) =>
market.baseTokenId === token.tokenId ||
market.quoteTokenId === token.tokenId
)
);
if (
filteredToTokens &&
filteredToTokens.length > 0 &&
toToken &&
!filteredToTokens.find(
(token) => token.tokenId === toToken.tokenId
)
) {
setToToken(filteredToTokens[0]);
setToAmount("");
}
setFilteredToTokens(filteredToTokens);
}
}, [
compatibleMarkets,
fromToken,
supportedMarkets,
supportedTokens,
toToken,
]);
// on valid "from" and "to" tokens setting, we need to find their current exchange rate
useEffect(() => {
if (
supportedTokens &&
supportedTokens.length > 0 &&
fromToken &&
toToken &&
!liquidityError &&
// when the exchange rate is used to calculate the expected to or from token amount,
// and that is enforced on the component's state, this effect is invoked again and again
// until the currently fetched exchange rate is the same as the previous.
// In particularly traded markets, where the order book changes often, this produces an
// annoying flickering effect. We avoid it by calculating from and to amounts only if
// an actual user interacted with the form (NOT when the app updates the to and
// from amounts after swap-details-related calculations)
((!changingFromAmount &&
!changingToAmount &&
fromAmount &&
toAmount) ||
(changingFromAmount && fromAmount) ||
(changingToAmount && toAmount))
) {
const tradedMarket = compatibleMarkets.find(
(market) =>
(market.baseTokenId === toToken.tokenId &&
market.quoteTokenId === fromToken.tokenId) ||
(market.baseTokenId === fromToken.tokenId &&
market.quoteTokenId === toToken.tokenId)
);
if (!tradedMarket) {
return;
}
debouncedGetSwapData(
loopringWallet,
loopringAccount,
supportedTokens.find(
(token) => token.tokenId === tradedMarket.baseTokenId
),
supportedTokens.find(
(token) => token.tokenId === tradedMarket.quoteTokenId
),
fromAmount,
supportedTokens,
selling
);
}
}, [
loopringWallet,
loopringAccount,
changingFromAmount,
changingToAmount,
compatibleMarkets,
debouncedGetSwapData,
liquidityError,
fromAmount,
fromToken,
selling,
supportedTokens,
toAmount,
toToken,
]);
// when the exchange rate is fetched, we need to calculate the expected
// token amount to receive based on it
useEffect(() => {
if (
swapData &&
swapData.averageFillPrice &&
fromToken &&
toToken &&
((!changingFromAmount &&
!changingToAmount &&
fromAmount &&
toAmount) ||
(changingFromAmount && fromAmount) ||
(changingToAmount && toAmount))
) {
const referenceAmount = changingToAmount ? toAmount : fromAmount;
let partialAmount = new BigNumber(referenceAmount);
if (changingToAmount) {
partialAmount = selling
? partialAmount.dividedBy(swapData.averageFillPrice)
: partialAmount.multipliedBy(swapData.averageFillPrice);
} else {
partialAmount = selling
? partialAmount.multipliedBy(swapData.averageFillPrice)
: partialAmount.dividedBy(swapData.averageFillPrice);
}
const newAmount = partialAmount.toFixed();
let newFromAmount = fromAmount;
let newToAmount = toAmount;
if (changingToAmount && newAmount !== fromAmount) {
// if the updated to amount is more than the maximum one based on
// the order book, the maximum possible value is set
newFromAmount = newAmount;
setLiquidityError(
!!(
swapData.maximumAmount &&
new BigNumber(newAmount)
.dividedBy(swapData.averageFillPrice)
.isGreaterThan(swapData.maximumAmount)
)
);
} else if (!changingToAmount && newAmount !== toAmount) {
// If the new from amount would bring, based on the current average
// fill price, the to token amount to be bigger than the maximum allowed
// quantity, the from amount is adjusted accordingly
newToAmount = newAmount;
setLiquidityError(
!!(
swapData.maximumAmount &&
swapData.maximumAmount.isLessThan(newAmount)
)
);
}
setFromAmount(newFromAmount);
const feeAmount = new BigNumber(newToAmount).multipliedBy(
swapData.feePercentage
);
setToAmount(new BigNumber(newToAmount).minus(feeAmount).toFixed());
setFeeAmount(feeAmount);
setChangingFromAmount(false);
setChangingToAmount(false);
}
}, [
changingFromAmount,
changingToAmount,
fromAmount,
fromToken,
selling,
swapData,
toAmount,
toToken,
]);
// on "from" or "to" token changes, we need to determine if the user is buying or selling a given market.
// We do this by checking if the corresponding market has the "from" token as a base or quote currency.
// If the "from" token is a quote currency, the user is buying, and vice-versa.
useEffect(() => {
if (fromToken && toToken) {
setSelling(
!!compatibleMarkets.find(
(market) =>
market.baseTokenId === fromToken.tokenId &&
market.quoteTokenId === toToken.tokenId
)
);
}
}, [compatibleMarkets, fromToken, toToken]);
useEffect(() => {
if (
(!fromAmount && toAmount && changingFromAmount) ||
(!toAmount && fromAmount && changingToAmount)
) {
setToAmount("");
dispatch(resetSwapData());
setLiquidityError(false);
setBalanceError(false);
setLessThanMinimumOrderError(false);
setMoreThanMaximumOrderError(false);
}
}, [changingFromAmount, dispatch, changingToAmount, fromAmount, toAmount]);
useEffect(() => {
if (!fromToken || !toToken) {
return;
}
const wrappedBalance = balances.find(
(balance) => balance.id === fromToken.tokenId
);
const tokenMaximumExchangeBalance =
wrappedBalance && wrappedBalance.balance;
const bigNumberFromAmount = new BigNumber(fromAmount);
const bigNumberToAmount = new BigNumber(toAmount);
setBalanceError(
!!(
tokenMaximumExchangeBalance &&
bigNumberFromAmount.isGreaterThan(tokenMaximumExchangeBalance)
)
);
const fromTokenMinimumTradeVolume = weiToEther(
new BigNumber(fromToken.minOrderAmount),
fromToken.decimals
);
const toTokenMinimumTradeVolume = weiToEther(
new BigNumber(toToken.minOrderAmount),
toToken.decimals
);
setLessThanMinimumOrderError(
!!(
!bigNumberFromAmount.isZero() &&
!bigNumberToAmount.isZero() &&
(bigNumberFromAmount.isLessThan(fromTokenMinimumTradeVolume) ||
bigNumberToAmount.isLessThan(toTokenMinimumTradeVolume))
)
);
const fromTokenMaximumTradeVolume = weiToEther(
new BigNumber(fromToken.maxOrderAmount),
fromToken.decimals
);
const toTokenMaximumTradeVolume = weiToEther(
new BigNumber(toToken.maxOrderAmount),
toToken.decimals
);
setMoreThanMaximumOrderError(
!!(
!bigNumberFromAmount.isZero() &&
!bigNumberToAmount.isZero() &&
(bigNumberFromAmount.isGreaterThan(
fromTokenMaximumTradeVolume
) ||
bigNumberToAmount.isGreaterThan(toTokenMaximumTradeVolume))
)
);
}, [balances, fromAmount, fromToken, toAmount, toToken]);
const handleFromAmountChange = useCallback((amount) => {
setChangingToAmount(false);
setChangingFromAmount(true);
setFromAmount(amount);
}, []);
const handleToAmountChange = useCallback((weiAmount) => {
setChangingToAmount(true);
setChangingFromAmount(false);
setToAmount(weiAmount);
}, []);
const handleSwap = useCallback(() => {
dispatch(
postSwap(
loopringAccount,
loopringWallet,
loopringExchange,
fromToken,
fromAmount,
toToken,
toAmount,
supportedTokens,
selling
)
);
}, [
dispatch,
fromAmount,
fromToken,
loopringAccount,
loopringExchange,
loopringWallet,
selling,
supportedTokens,
toAmount,
toToken,
]);
const handleBalancesRefresh = useCallback(() => {
if (
loggedIn &&
loopringAccount &&
loopringWallet &&
supportedTokens &&
supportedTokens.length > 0
) {
dispatch(
getUserBalances(
loopringAccount,
loopringWallet,
supportedTokens
)
);
}
}, [dispatch, loggedIn, loopringAccount, loopringWallet, supportedTokens]);
const handleAssetsInversion = useCallback(() => {
if (fromToken && toToken) {
setFromAmount("");
setToAmount("");
setFromToken(toToken);
setToToken(fromToken);
setLiquidityError(false);
setBalanceError(false);
setLessThanMinimumOrderError(false);
setMoreThanMaximumOrderError(false);
dispatch(resetSwapData());
}
}, [fromToken, toToken, dispatch]);
const getErrorCause = () => {
if (moreThanMaximumOrderError) {
return "maximum";
}
if (liquidityError) {
return "liquidity";
}
if (balanceError) {
return "balance";
}
if (lessThanMinimumOrderError) {
return "minimum";
}
return null;
};
const getPriceNotation = () => {
let price;
const priceFromToken = flippedPriceNotation ? fromToken : toToken;
const priceToToken = flippedPriceNotation ? toToken : fromToken;
if (selling) {
price = flippedPriceNotation
? new BigNumber("1").dividedBy(swapData.averageFillPrice)
: swapData.averageFillPrice;
} else {
price = flippedPriceNotation
? swapData.averageFillPrice
: new BigNumber("1").dividedBy(swapData.averageFillPrice);
}
return `${formatNumber(price, {
style: "decimal",
maximumSignificantDigits: 4,
})} ${priceFromToken.symbol} per ${priceToToken.symbol}`;
};
const handlePriceFlip = useCallback(() => {
setFlippedPriceNotation(!flippedPriceNotation);
}, [flippedPriceNotation]);
return (
<Flex flexDirection="column">
<BackgroundFlex flexDirection="column" alignItems="center" mb={4}>
<Box>
<TokenSpecifier
variant="from"
amount={fromAmount}
token={fromToken}
onAmountChange={handleFromAmountChange}
onBalancesRefresh={handleBalancesRefresh}
onTokenChange={setFromToken}
supportedTokens={supportedTokens}
balances={balances}
loadingSupportedTokens={loadingSupportedTokens}
loadingBalances={loadingBalances}
loggedIn={loggedIn}
/>
</Box>
<PointableBox
display="flex"
justifyContent="center"
alignItems="center"
height={36}
p={2}
onClick={handleAssetsInversion}
>
<ArrowIcon icon={faArrowDown} />
</PointableBox>
<Box mb="12px">
<TokenSpecifier
variant="to"
amount={toAmount}
token={toToken}
onAmountChange={handleToAmountChange}
onBalancesRefresh={handleBalancesRefresh}
onTokenChange={setToToken}
supportedTokens={filteredToTokens}
balances={balances}
loadingSupportedTokens={loadingSupportedTokens}
loadingBalances={loadingBalances}
loggedIn={loggedIn}
/>
</Box>
<Flex
mb="8px"
justifyContent="space-between"
alignItems="center"
px={2}
height="12px"
width="100%"
>
{(liquidityError ||
balanceError ||
lessThanMinimumOrderError ||
moreThanMaximumOrderError) && (
<>
<ErrorTextBox>
<FormattedMessage
id={`swapper.error.amount.${getErrorCause()}`}
/>
</ErrorTextBox>
<ErrorTextBox>
<FontAwesomeIcon icon={faExclamationTriangle} />
</ErrorTextBox>
</>
)}
</Flex>
<Flex
mb="8px"
justifyContent="space-between"
alignItems="center"
px={2}
width="100%"
>
<Box>
<FormattedMessage id="swapper.price" />
</Box>
<Box>
{loadingSwapData ? (
<Spinner size={12} />
) : swapData && swapData.averageFillPrice ? (
<Flex>
<Box mr="4px">{getPriceNotation()}</Box>
<PointableBox onClick={handlePriceFlip}>
<PriceFlipIcon icon={faRandom} />
</PointableBox>
</Flex>
) : (
"-"
)}
</Box>
</Flex>
<Flex
mb="8px"
justifyContent="space-between"
alignItems="center"
px={2}
width="100%"
>
<Box>
<FormattedMessage id="swapper.slippage" />
</Box>
<Box>
{loadingSwapData ? (
<Spinner size={12} />
) : swapData && swapData.slippagePercentage ? (
<SlippageText>
{formatNumber(swapData.slippagePercentage, {
style: "decimal",
maximumSignificantDigits: 4,
})}
%
</SlippageText>
) : (
"-"
)}
</Box>
</Flex>
<Flex
justifyContent="space-between"
alignItems="center"
px={2}
width="100%"
>
<Box>
<FormattedMessage id="swapper.fee" />
</Box>
<Box>
{feeAmount && feeAmount.isGreaterThan("0")
? `${formatNumber(feeAmount, {
style: "decimal",
maximumSignificantDigits: 4,
})} ${toToken.symbol}`
: "-"}
</Box>
</Flex>
</BackgroundFlex>
<Box display="flex" justifyContent="center" mb={4}>
<Button
faIcon={loggedIn ? faExchangeAlt : faLockOpen}
size="large"
loading={loggedIn && loadingSwapSubmission}
disabled={
loggedIn &&
(liquidityError ||
balanceError ||
lessThanMinimumOrderError ||
moreThanMaximumOrderError ||
!fromToken ||
!fromAmount ||
fromAmount === "0" ||
!toToken ||
!toAmount ||
toAmount === "0")
}
onClick={loggedIn ? handleSwap : onConnectWalletClick}
>
<FormattedMessage
id={`swapper.action.${loggedIn ? "swap" : "connect"}`}
/>
</Button>
</Box>
</Flex>
);
}
Example #6
Source File: Navigation.jsx From jitsi-party with MIT License | 4 votes |
render() {
const onClick = this.props.onClick;
const { north, south, east, west } = this.props.directions || {};
const mapButtonClass = this.props.showMapTooltip
? "map-button animated"
: "map-button";
const pokeButtonClass = this.state.showPokeOptions
? "poke-button focused"
: "poke-button";
const room = this.props.currentRoom.room;
const audio = this.props.rooms[room].audio;
const roomType = this.props.rooms[room].type;
const events = this.props.events;
const users = _.flatten(Object.values(this.props.users));
const handleClickMap = () => this.props.handleOpenModal("map");
const handleClickEvents = () => this.props.handleOpenModal("events");
const handleClickEmail = () => this.props.handleOpenModal("email");
return (
<div className="navigation-container">
<div className="column settings-container">
<div className="map-button-container">
{this.props.showMapButton && !this.props.hideSettings && (
<button
className={mapButtonClass}
title={Config.tooltips.map}
disabled={false}
onClick={handleClickMap}
>
<FontAwesomeIcon icon={faMap} />
</button>
)}
{/* {this.props.showMapTooltip &&
<div className="map-tooltip">you have unlocked the party map!</div>
} */}
</div>
<div className="events-button-container">
{events && events.length > 0 && !this.props.hideSettings && (
<button
className="events-button"
title={Config.tooltips.events}
onClick={handleClickEvents}
>
<FontAwesomeIcon icon={faCalendar} />
</button>
)}
</div>
<div className="email-button-container">
{Config.moderation &&
!_.isEmpty(Config.moderation.moderatorEmails) && (
<button
className="email-button"
title={Config.tooltips.moderator}
onClick={handleClickEmail}
>
<FontAwesomeIcon icon={faEnvelope} />
</button>
)}
</div>
{roomType.toUpperCase() === "CHATSTREAM" &&
this.props.currentRoom.entered &&
!this.props.hideSettings ? (
<div className="chat-button-container">
<button
className={mapButtonClass}
title={Config.tooltips.chat}
disabled={false}
onClick={() =>
this.setState({ hideChat: !this.state.hideChat })
}
>
<FontAwesomeIcon icon={faCommentAlt} />
</button>
</div>
) : null}
<div className="poke-button-container">
{Config.poke &&
this.props.isPokingUnlocked &&
!this.props.hideSettings && (
<button
className={pokeButtonClass}
title={Config.tooltips.poke}
onClick={this.handleClickPokeButton.bind(this)}
>
<FontAwesomeIcon icon={Config.poke.fontAwesomeIcon} />
</button>
)}
{this.state.showPokeOptions && (
<PokeOptions
users={users}
handlePoke={this.handlePoke.bind(this)}
/>
)}
</div>
<div className="audio-button-container">
{audio && (
<AudioPlayer
src={audio.path}
autoPlay={audio.autoPlay}
hide={audio.hideControls}
onChange={this.handleAudioChanged.bind(this)}
></AudioPlayer>
)}
</div>
</div>
<div className="column">
<button
className="west"
disabled={!west}
onClick={() => onClick(west)}
>
<FontAwesomeIcon icon={faArrowLeft} />
<span className="navigation-room-name">
{_.get(this.props.rooms[west], "name")}
</span>
</button>
</div>
<div className="column">
<button
className="north"
disabled={!north}
onClick={() => onClick(north)}
>
<FontAwesomeIcon icon={faArrowUp} />
<span className="navigation-room-name">
{_.get(this.props.rooms[north], "name")}
</span>
</button>
<button
className="south"
disabled={!south}
onClick={() => onClick(south)}
>
<FontAwesomeIcon icon={faArrowDown} />
<span className="navigation-room-name">
{_.get(this.props.rooms[south], "name")}
</span>
</button>
</div>
<div className="column">
<button
className="east"
disabled={!east}
onClick={() => onClick(east)}
>
<FontAwesomeIcon icon={faArrowRight} />
<span className="navigation-room-name">
{_.get(this.props.rooms[east], "name")}
</span>
</button>
</div>
<div className="column column-avatar">
<div className="puck-wrapper">
<img
src={
Config.avatars[this.props.user.avatar.type].images[
this.props.user.avatar.color
]
}
/>
</div>
</div>
</div>
);
}