lodash#orderBy JavaScript Examples
The following examples show how to use
lodash#orderBy.
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: helpers.js From paigeniedringhaus.com with MIT License | 6 votes |
sortArrayByDate = (arr) => {
const sortedArr = orderBy(
arr,
(item) => {
return moment(item.date).format('YYYYMMDD');
},
['desc'],
);
return sortedArr;
}
Example #2
Source File: index.js From hzero-front with Apache License 2.0 | 6 votes |
/**
* 查询api调用总数
*/
@Bind()
queryApiInvokeCount(startTime, endTime) {
const beginDate = startTime.format().split('T')[0];
const endDate = endTime.format().split('T')[0];
this.setState({ apiInvokeLoading: true });
const params = {
beginDate,
endDate,
};
fetchApiInvokeCount(params).then((res) => {
let obj = {};
if (res && !res.failed) {
const { details = [], entities = [] } = res;
if (details.length && entities.length) {
const handleDetails = details.map((item) => ({
...item,
sortIndex: entities.indexOf(item.service),
}));
const finalDetails = orderBy(handleDetails, ['sortIndex'], ['asc']);
res.details = finalDetails;
}
obj = res;
}
this.setState({
apiInvokeData: obj,
apiInvokeLoading: false,
});
});
this.getApiInvokeChart();
}
Example #3
Source File: ObjectListItemSources.js From sampo-ui with MIT License | 6 votes |
ObjectListItemSources = props => {
let { data, externalLink } = props
data = Array.isArray(data) ? data : [data]
data = orderBy(data, 'prefLabel')
return (
<sup>
{data.map((source, index) =>
<React.Fragment key={source.id}>
<ObjectListItemLink
externalLink={externalLink}
data={source}
label={source.prefLabel}
/>
{!(data.length === index + 1) && <span>, </span>}
</React.Fragment>
)}
</sup>
)
}
Example #4
Source File: LeafletConfig.js From sampo-ui with MIT License | 6 votes |
createInstanceListing = instances => {
let root
if (Array.isArray(instances)) {
root = document.createElement('ul')
instances = orderBy(instances, 'prefLabel')
instances.forEach(i => {
const li = document.createElement('li')
const link = document.createElement('a')
link.addEventListener('click', () => history.push(i.dataProviderUrl))
link.textContent = i.prefLabel
link.style.cssText = 'cursor: pointer; text-decoration: underline'
li.appendChild(link)
root.appendChild(li)
})
} else {
root = document.createElement('p')
const link = document.createElement('a')
link.addEventListener('click', () => history.push(instances.dataProviderUrl))
link.textContent = instances.prefLabel
link.style.cssText = 'cursor: pointer; text-decoration: underline'
root.appendChild(link)
}
return root
}
Example #5
Source File: country.js From rakning-c19-app with MIT License | 6 votes |
getAll() {
if (!this.countries) {
this.countries = orderBy(
this.countriesData || require('./resources/countries.json'),
['name'],
['asc'],
);
}
return this.countries;
}
Example #6
Source File: StatChart.js From covid19 with MIT License | 6 votes |
StatChart = ({ data, dataKey, color }) => {
const sortedData = orderBy(data, 'date.date')
return (
<ResponsiveContainer width="100%" height={128}>
<LineChart data={sortedData}>
<Tooltip
separator=""
formatter={(value) => [commaNumber(value)]}
labelFormatter={() => ''}
/>
<Line
type="monotone"
dataKey={dataKey}
stroke={theme.colors[color]}
strokeWidth={3}
dot={false}
/>
</LineChart>
</ResponsiveContainer>
)
}
Example #7
Source File: index.js From gobench with Apache License 2.0 | 6 votes |
getMetricDataPolling = async (metrics, oldData = []) => {
return await Promise.all(metrics.map(mtr => {
const oldMetricData = oldData.find(o => mtr.id === get(o, ['id'], ''))
const timestamp = get(oldMetricData, 'lastTimestamp', '')
return getMetricData(mtr.id, mtr.type, timestamp)
.then(mData => {
if (mData.length > 0) {
const dataByType = getDataByType(mData, mtr.type)
const oldMetricChartData = get(oldMetricData, ['chartData', 'data'], [])
const newData = [...oldMetricChartData, ...dataByType]
return {
...oldMetricData,
lastTimestamp: get(orderBy(mData, ['time'], 'desc'), '[0].time'),
chartData: {
name: mtr.title,
data: newData
}
}
}
return oldMetricData
})
}))
.then(rs => rs)
.catch(err => err)
}
Example #8
Source File: RelatedNews.js From ecomloop.github.io with MIT License | 5 votes |
getRelatedNews = (currentNews, allNews) => {
const maxPosts = 3;
const currentCategories = (currentNews.extractedkeywords + "," + currentNews.keywords).split(",") || [];
const currentTags = currentNews.tags.split(",") || [];
// console.log("******** in related news")
// console.log(allNews)
// console.log(currentNews)
// console.log(currentCategories)
// console.log(currentTags)
// Don't include the current post in posts list
allNews = allNews.filter((post) => post.node.id !== currentNews.id);
const identityMap = {};
//Map over all posts, add to map and add points
for (let post of allNews) {
const id = post.node.id;
if (!identityMap.hasOwnProperty(id)) {
identityMap[id] = {
news: post,
points: 0
}
}
// For category matches, we add 2 points
const categoryPoints = 2;
const categories = (post.node.extractedkeywords + "," + post.node.keywords).split(",") || [];
categories.forEach((category) => {
if (includes(...currentCategories, category)) {
identityMap[id].points += categoryPoints;
}
})
// For tags matches, we add 1 point
const tagPoint = 1;
const tags = post.node.tags.split(",") || [];
tags.forEach((aTag) => {
if (includes(currentTags, aTag)) {
identityMap[id].points += tagPoint;
}
})
}
// Convert the identity map to an array
const arrayIdentityMap = Object.keys(identityMap).map((id) => identityMap[id]);
// Use a lodash utility function to sort them
// by points, from greatest to least
const similarPosts = orderBy(
arrayIdentityMap, ['points'], ['desc']
)
//console.log("***** relatedNews Output ",similarPosts.splice(0, maxPosts))
// return the max number posts requested
return similarPosts.splice(0, maxPosts);
}
Example #9
Source File: reducers.js From chromeless with Mozilla Public License 2.0 | 5 votes |
filteredSortedAppIds = (state = null, action) => {
switch (action.type) {
case INSTALLED_UPDATE_SORTED_APP_IDS: {
return action.sortedAppIds;
}
case CLEAN_APP_MANAGEMENT: {
// keep apps which are in installing/updating state
if (!state) return null;
const newLst = state.filter((id) => (action.apps[id].status === INSTALLING));
return newLst;
}
case SET_APP: {
if (!state) return null;
// if the app is not supposed to be in search result
// just return the current state
const processedQuery = action.activeQuery.trim().toLowerCase();
const currentApp = { ...action.apps[action.id], ...action.app };
if (!(
currentApp.name.toLowerCase().includes(processedQuery)
|| (currentApp.url && currentApp.url.toLowerCase().includes(processedQuery))
)) {
return state;
}
// if id is not in list, insert at sorted position
if (state.indexOf(action.id) < 0) {
const index = sortedIndexBy(state, action.id, (id) => {
const app = id === action.id ? { ...action.apps[id], ...action.app } : action.apps[id];
return iterateeFunc(app, action.sortInstalledAppBy);
});
state.splice(index, 0, action.id);
return [...state];
}
// if sorting value is updated, remove and reinsert id at new index
if (
(action.sortInstalledAppBy === 'name' && action.app.name)
|| (action.sortInstalledAppBy === 'last-updated' && (action.app.lastUpdated))
) {
const newState = without(state, action.id);
const index = sortedIndexBy(newState, action.id, (id) => {
const app = id === action.id ? { ...action.apps[id], ...action.app } : action.apps[id];
return iterateeFunc(app, action.sortInstalledAppBy);
});
newState.splice(index, 0, action.id);
return newState;
}
return state;
}
case REMOVE_APP: {
if (!state) return null;
return without(state, action.id);
}
case SORT_APPS: {
if (!state) return null;
// resort
return orderBy(state, (id) => {
const app = action.apps[id];
return iterateeFunc(app, action.sortInstalledAppBy);
});
}
default: return state;
}
}
Example #10
Source File: reducers.js From chromeless with Mozilla Public License 2.0 | 5 votes |
sortedAppIds = (state = [], action) => {
switch (action.type) {
case CLEAN_APP_MANAGEMENT: {
// keep apps which are in installing/updating state
const newLst = state.filter((id) => (action.apps[id].status === INSTALLING));
return newLst;
}
case SET_APP: {
// if id is not in list, insert at sorted position
if (state.indexOf(action.id) < 0) {
const index = sortedIndexBy(state, action.id, (id) => {
const app = id === action.id ? { ...action.apps[id], ...action.app } : action.apps[id];
return iterateeFunc(app, action.sortInstalledAppBy);
});
state.splice(index, 0, action.id);
return [...state];
}
// if sorting value is updated, remove and reinsert id at new index
if (
(action.sortInstalledAppBy === 'name' && action.app.name)
|| (action.sortInstalledAppBy === 'last-updated' && (action.app.lastUpdated))
) {
const newState = without(state, action.id);
const index = sortedIndexBy(newState, action.id, (id) => {
const app = id === action.id ? { ...action.apps[id], ...action.app } : action.apps[id];
return iterateeFunc(app, action.sortInstalledAppBy);
});
newState.splice(index, 0, action.id);
return newState;
}
return state;
}
case REMOVE_APP: {
return without(state, action.id);
}
case SORT_APPS: {
// resort
const parts = action.sortInstalledAppBy.split('/');
const key = parts[0];
const order = parts.length > 0 ? parts[1] : 'asc';
return orderBy(state, (id) => {
const app = action.apps[id];
return iterateeFunc(app, key);
}, [order]);
}
default: return state;
}
}
Example #11
Source File: index.js From hzero-front with Apache License 2.0 | 5 votes |
render() {
const {
tenantInitLog: { logList, pagination, enumMap, picData },
listLoading,
picLoading = false,
} = this.props;
const { currentLog, isShowImg } = this.state;
let imgData = {};
if (!isEmpty(picData)) {
imgData = groupBy(orderBy(picData, 'orderSeq'), 'processorType');
}
const filterProps = {
onSearch: this.handleSearch,
onRef: this.handleBindRef,
enumMap,
};
const listProps = {
isShowImg,
dataSource: logList,
pagination,
picProps: {
dataSource: imgData,
loading: picLoading,
type: !isEmpty(currentLog) && currentLog.initType.toLowerCase(),
},
loading: listLoading,
onChange: this.handleSearch,
onSearchPic: this.handleSearchPic,
onOpenPic: this.handleOpenImgModal,
onClosePic: this.handleCloseImgModal,
};
return (
<>
<Header title={intl.get(`${viewTitle}.tenant.init.log`).d('租户初始化处理日志')} />
<Content>
<FilterForm {...filterProps} />
<ListTable {...listProps} />
</Content>
</>
);
}
Example #12
Source File: networkService.js From web-wallet with Apache License 2.0 | 5 votes |
async getBalances () {
try {
const _childchainBalances = await this.childChain.getBalance(this.account);
const childchainBalances = await Promise.all(_childchainBalances.map(
async i => {
const token = await getToken(i.currency);
return {
...token,
amount: i.amount.toString()
};
}
));
const rootErc20Balances = await Promise.all(childchainBalances.map(
async i => {
if (i.name !== 'ETH') {
const balance = await OmgUtil.getErc20Balance({
web3: this.web3,
address: this.account,
erc20Address: i.currency
});
return {
...i,
amount: balance.toString()
};
}
}
));
const _rootEthBalance = await this.web3.eth.getBalance(this.account);
const ethToken = await getToken(OmgUtil.transaction.ETH_CURRENCY);
const rootchainEthBalance = {
...ethToken,
amount: _rootEthBalance
};
return {
rootchain: orderBy([ rootchainEthBalance, ...rootErc20Balances.filter(i => !!i) ], i => i.currency),
childchain: orderBy(childchainBalances, i => i.currency)
};
} catch (error) {
throw new WebWalletError({
originalError: error,
reportToSentry: false,
reportToUi: false
});
}
}
Example #13
Source File: Deposits.js From web-wallet with Apache License 2.0 | 5 votes |
function Deposits ({ searchHistory }) {
const [ page, setPage ] = useState(1);
const ethDeposits = useSelector(selectEthDeposits, isEqual);
const erc20Deposits = useSelector(selectErc20Deposits, isEqual);
const loading = useSelector(selectLoading([ 'DEPOSIT/GETALL' ]));
useEffect(() => {
setPage(1);
}, [ searchHistory ]);
const deposits = orderBy(
[ ...ethDeposits, ...erc20Deposits ],
i => i.blockNumber, 'desc'
);
const _deposits = deposits.filter(i => {
return i.transactionHash.includes(searchHistory) || i.returnValues.token.includes(searchHistory);
});
const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE);
const endingIndex = page * PER_PAGE;
const paginatedDeposits = _deposits.slice(startingIndex, endingIndex);
return (
<div className={styles.transactionSection}>
<div className={styles.transactions}>
<Pager
currentPage={page}
isLastPage={paginatedDeposits.length < PER_PAGE}
onClickNext={() => setPage(page + 1)}
onClickBack={() => setPage(page - 1)}
/>
{!paginatedDeposits.length && !loading && (
<div className={styles.disclaimer}>No deposit history.</div>
)}
{!paginatedDeposits.length && loading && (
<div className={styles.disclaimer}>Loading...</div>
)}
{paginatedDeposits.map((i, index) => {
return (
<Transaction
key={index}
link={`${config.etherscanUrl}/tx/${i.transactionHash}`}
title={truncate(i.transactionHash, 6, 4, '...')}
midTitle='Deposit'
subTitle={`Token: ${i.tokenInfo.name}`}
status={i.status === 'Pending' ? 'Pending' : logAmount(i.returnValues.amount, i.tokenInfo.decimals)}
statusPercentage={i.pendingPercentage <= 100 ? i.pendingPercentage : ''}
subStatus={`Block ${i.blockNumber}`}
tooltip={'For re-org protection, deposits require 10 block confirmations before the UTXO is available to spend.'}
/>
);
})}
</div>
</div>
);
}
Example #14
Source File: StatsCell.js From covid19 with MIT License | 5 votes |
Success = ({ countries = [], country = 'usa' }) => {
// Calculate stats
const [counts, setCounts] = useState([])
const stat = (key) =>
commaNumber(last(map(orderBy(counts, 'date.date'), key)))
useEffect(() => {
setCounts(find(countries, ['iso', country])?.dailyCounts)
}, [country])
return (
<div>
<section>
<StatChart data={counts} dataKey="newCases" color="green" />
<Stat value={stat('newCases')} label="New cases" />
</section>
<section>
<StatChart data={counts} dataKey="currentlyInfected" color="yellow" />
<Stat value={stat('currentlyInfected')} label="Currently infected" />
</section>
<section>
<StatChart data={counts} dataKey="totalCases" color="orange" />
<Stat value={stat('totalCases')} label="Confirmed cases" />
</section>
<section>
<StatChart data={counts} dataKey="totalDeaths" color="red" />
<Stat value={stat('totalDeaths')} label="Confirmed deaths" />
</section>
<style jsx>{`
div {
display: grid;
grid-gap: 1rem;
margin-top: 2rem;
}
@media (min-width: 48em) {
div {
grid-template-columns: repeat(4, 1fr);
}
}
section {
position: relative;
min-height: 8rem;
}
section :global(.recharts-responsive-container) {
position: absolute !important;
top: 0;
left: 0;
right: 0;
}
`}</style>
</div>
)
}
Example #15
Source File: tableUtil.js From lens-extension-cc with MIT License | 5 votes |
sortData = (obj, sortBy, order, path) => {
const sortByValueArr = Object.keys(obj).map((key) => {
return { [key]: get(obj[key], path[sortBy]) };
});
const sorted = orderBy(sortByValueArr, Object.keys(obj), [order]);
return sorted.map(Object.keys);
}
Example #16
Source File: RelatedPosts.js From ecomloop.github.io with MIT License | 5 votes |
getRelatedPosts = (currentPost, allPosts) => {
const maxPosts = 3;
const currentCatetory = currentPost.node.frontmatter.categories || "";
const currentTags = currentPost.node.frontmatter.tags || [];
// console.log("******** in related post")
// console.log(allPosts)
// console.log(currentPost)
// console.log(currentCatetory)
// console.log(currentTags)
// Don't include the current post in posts list
allPosts = allPosts.filter((post) => post.node.id !== currentPost.node.id);
const identityMap = {};
//Map over all posts, add to map and add points
for (let post of allPosts) {
const id = post.node.id;
if (!identityMap.hasOwnProperty(id)) {
identityMap[id] = {
post: post,
points: 0
}
}
// For category matches, we add 2 points
const categoryPoints = 2;
//if (post.node.frontmatter.categories.category === currentCatetory) {
//identityMap[id].points += categoryPoints;
//}
post.node.frontmatter.categories.forEach(({category}) => {
if (includes(...currentCatetory, category)) {
identityMap[id].points += categoryPoints;
}
})
// For tags matches, we add 1 point
const tagPoint = 1;
post.node.frontmatter.tags.forEach((aTag) => {
if (includes(currentTags, aTag)) {
identityMap[id].points += tagPoint;
}
})
}
// Convert the identity map to an array
const arrayIdentityMap = Object.keys(identityMap).map((id) => identityMap[id]);
// Use a lodash utility function to sort them
// by points, from greatest to least
const similarPosts = orderBy(
arrayIdentityMap, ['points'], ['desc']
)
//console.log(similarPosts.splice(0, maxPosts))
// return the max number posts requested
return similarPosts.splice(0, maxPosts);
}
Example #17
Source File: RelatedShops.jsx From emprezzo with MIT License | 5 votes |
getRelatedShops = (currentShop, allshops) => {
const maxPosts = 4;
const currentCategories = currentShop.category?currentShop.category.split(","):[];
const currentTags = currentShop.tags?currentShop.tags.split(","):[];
// console.log("******** in related shops")
// console.log(allshops)
// console.log(currentShop)
// console.log(currentCategories)
// console.log(currentTags)
// Don't include the current post in posts list
allshops = allshops.filter((post) => post.id !== currentShop.id);
const identityMap = {};
//Map over all posts, add to map and add points
for (let post of allshops) {
const id = post.id;
if (!identityMap.hasOwnProperty(id)) {
identityMap[id] = {
shop: post,
points: 0
}
}
// For category matches, we add 2 points
const categoryPoints = 2;
const categories = post.category?post.category.split(","):[];
categories.forEach((category) => {
if (includes(...currentCategories, category)) {
identityMap[id].points += categoryPoints;
}
})
// For tags matches, we add 1 point
const tagPoint = 1;
const tags = post.tags?post.tags.split(","):[];
tags.forEach((aTag) => {
if (includes(currentTags, aTag)) {
identityMap[id].points += tagPoint;
}
})
}
// Convert the identity map to an array
const arrayIdentityMap = Object.keys(identityMap).map((id) => identityMap[id]);
// Use a lodash utility function to sort them
// by points, from greatest to least
const similarPosts = orderBy(
arrayIdentityMap, ['points'], ['desc']
)
//console.log("***** relatedShops Output ",similarPosts.splice(0, maxPosts))
// return the max number posts requested
return similarPosts.splice(0, maxPosts);
}
Example #18
Source File: fullTextSearch.js From sampo-ui with MIT License | 5 votes |
handleFullTextSearchAction = (state, action, initialState) => {
switch (action.type) {
case FETCH_FULL_TEXT_RESULTS:
return {
...state,
fetching: true
}
case UPDATE_RESULTS:
return {
...state,
query: action.query,
results: action.data,
fetching: false
}
case CLEAR_RESULTS:
return initialState
case SORT_FULL_TEXT_RESULTS: {
let sortBy
let sortDirection
if (action.sortBy === state.sortBy) {
sortBy = state.sortBy
sortDirection = state.sortDirection === 'asc' ? 'desc' : 'asc'
}
if (action.sortBy !== state.sortBy) {
sortBy = action.sortBy
sortDirection = 'asc'
}
const sortByProperty = state.properties.find(property => property.id === sortBy)
const sortByPath = sortByProperty.valueType === 'object' ? `${sortBy}.prefLabel` : sortBy
return {
...state,
sortBy,
sortDirection,
results: orderBy(
state.results,
sortByPath,
sortDirection
)
}
}
default:
return state
}
}
Example #19
Source File: index.js From sampo-ui with MIT License | 5 votes |
filterResults = createSelector(
[getResults, getFacets, getLastlyUpdatedFacet, getSortBy, getSortDirection],
(results, facets, lastlyUpdatedFacet, sortBy, sortDirection) => {
if (results == null) {
return {
clientFSResults: null,
clientFSFacetValues: null
}
}
// Filter results by current facet selections
for (const [facetID, facet] of Object.entries(facets)) {
const { filterType, selectionsSet } = facet
if (filterType === 'clientFSLiteral' && selectionsSet.size !== 0) {
results = results.filter(result => selectionsSet.has(result[facetID]))
}
}
results = orderBy(results, sortBy, sortDirection)
// Calculate values for all facets
const facetValues = {}
let skipFacetID = ''
// Initialize the facetValues object with facet IDs
for (const facetId in facets) {
facetValues[facetId] = {}
}
// If a facet selection was added, first handle that facet
if (lastlyUpdatedFacet !== null) {
// console.log(lastlyUpdatedFacet.facetID)
// console.log(facets[lastlyUpdatedFacet.facetID])
skipFacetID = lastlyUpdatedFacet.facetID
lastlyUpdatedFacet.values = lastlyUpdatedFacet.values.map(value => ({
...value,
selected: facets[lastlyUpdatedFacet.facetID].selectionsSet.has(value.id)
}))
facetValues[lastlyUpdatedFacet.facetID] = lastlyUpdatedFacet.values
}
// Then handle all the remainder facets
for (const result of results) {
for (const [facetID, facet] of Object.entries(facets)) {
const { filterType, selectionsSet } = facet
if (facetID !== skipFacetID && filterType === 'clientFSLiteral' && has(result, facetID)) {
const literalValue = result[facetID]
if (!has(facetValues[facetID], literalValue)) {
facetValues[facetID][literalValue] = {
id: literalValue,
prefLabel: literalValue,
selected: selectionsSet.has(literalValue),
instanceCount: 1,
parent: null
}
} else {
facetValues[facetID][literalValue].instanceCount += 1
}
}
}
}
for (const facetID in facetValues) {
facetValues[facetID] = orderBy(facetValues[facetID], 'prefLabel')
}
// console.log(results)
// console.log(facetValues)
return {
clientFSResults: results,
clientFSFacetValues: facetValues
}
}
)
Example #20
Source File: TransformationsList.js From ui-data-export with Apache License 2.0 | 5 votes |
TransformationsList = ({
transformations,
allTransformations,
}) => {
const [sortedTransformations, setSortedTransformations] = useState([]);
const intl = useIntl();
const formatter = useMemo(() => ({
fieldName: record => {
const transformation = allTransformations.find(({ fieldId }) => fieldId === record.fieldId);
return transformation?.displayName;
},
transformation: record => (
<pre
title={record.transformation}
className={css.transformation}
>
{record.transformation}
</pre>
),
}), [allTransformations]);
const columnMapping = useMemo(() => ({
fieldName: intl.formatMessage({ id: 'ui-data-export.mappingProfiles.transformations.fieldName' }),
transformation: intl.formatMessage({ id: 'ui-data-export.mappingProfiles.transformations.transformation' }),
}), [intl]);
useEffect(() => {
const formattedTransformations = orderBy(transformations.map(transformation => ({
fieldName: formatter.fieldName(transformation),
transformation: formatter.transformation(transformation),
})), 'fieldName', 'asc');
setSortedTransformations(formattedTransformations);
}, [transformations, formatter]);
return (
<MultiColumnList
id="mapping-profile-transformations-list"
contentData={sortedTransformations}
columnMapping={columnMapping}
columnWidths={columnWidths}
visibleColumns={visibleColumns}
isEmptyMessage={intl.formatMessage({ id: 'ui-data-export.mappingProfiles.transformations.emptyMessage' })}
/>
);
}
Example #21
Source File: Exits.js From web-wallet with Apache License 2.0 | 4 votes |
function Exits ({ searchHistory }) {
const [ page, setPage ] = useState(1);
const [ processExitModal, setProcessExitModal ] = useState(false);
const pendingExits = orderBy(useSelector(selectPendingExits, isEqual), i => i.blockNumber, 'desc');
const exitedExits = orderBy(useSelector(selectExitedExits, isEqual), i => i.blockNumber, 'desc');
const loading = useSelector(selectLoading([ 'EXIT/GETALL' ]));
const _pendingExits = pendingExits.filter(i => {
return i.transactionHash.includes(searchHistory);
});
const _exitedExits = exitedExits.filter(i => {
return i.transactionHash.includes(searchHistory);
});
const renderPending = _pendingExits.map((i, index) => {
const exitableMoment = moment.unix(i.exitableAt);
const isExitable = moment().isAfter(exitableMoment);
function getStatus () {
if (i.status === 'Confirmed' && i.pendingPercentage >= 100) {
return 'In Challenge Period';
}
return i.status;
}
return (
<Transaction
key={`pending-${index}`}
button={
i.exitableAt && isExitable
? {
onClick: () => setProcessExitModal(i),
text: 'Process Exit'
}
: undefined
}
link={`${config.etherscanUrl}/tx/${i.transactionHash}`}
status={getStatus()}
subStatus={`Block ${i.blockNumber}`}
statusPercentage={i.pendingPercentage <= 100 ? i.pendingPercentage : ''}
title={truncate(i.transactionHash, 6, 4, '...')}
midTitle={i.exitableAt ? `Exitable ${exitableMoment.format('lll')}` : ''}
subTitle={i.currency ? truncate(i.currency, 6, 4, '...'): ''}
/>
);
});
const renderExited = _exitedExits.map((i, index) => {
return (
<Transaction
key={`exited-${index}`}
link={`${config.etherscanUrl}/tx/${i.transactionHash}`}
status='Exited'
subStatus={`Block ${i.blockNumber}`}
title={truncate(i.transactionHash, 6, 4, '...')}
/>
);
});
const allExits = [ ...renderPending, ...renderExited ];
const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE);
const endingIndex = page * PER_PAGE;
const paginatedExits = allExits.slice(startingIndex, endingIndex);
return (
<>
<ProcessExitsModal
exitData={processExitModal}
open={!!processExitModal}
toggle={() => setProcessExitModal(false)}
/>
<div className={styles.section}>
<div className={styles.subTitle}>Exits</div>
<div className={styles.transactionSection}>
<div className={styles.transactions}>
<Pager
currentPage={page}
isLastPage={paginatedExits.length < PER_PAGE}
onClickNext={() => setPage(page + 1)}
onClickBack={() => setPage(page - 1)}
/>
{!allExits.length && !loading && (
<div className={styles.disclaimer}>No exit history.</div>
)}
{!allExits.length && loading && (
<div className={styles.disclaimer}>Loading...</div>
)}
{React.Children.toArray(paginatedExits)}
</div>
</div>
</div>
</>
);
}
Example #22
Source File: FederatedResults.js From sampo-ui with MIT License | 4 votes |
FederatedResults = props => {
const { rootUrl, perspective, screenSize, clientFSState, layoutConfig, portalConfig } = props
const { searchMode } = perspective
const perspectiveID = perspective.id
const { maps } = clientFSState
const { mapClusters, mapMarkers } = maps
const layerControlExpanded = screenSize === 'md' ||
screenSize === 'lg' ||
screenSize === 'xl'
let groupedResults = []
if (props.location.pathname.endsWith('statistics')) {
const grouped = groupBy(props.clientFSResults, clientFSState.groupBy)
for (const key in grouped) {
groupedResults.push({
category: key,
prefLabel: key,
instanceCount: grouped[key].length
})
}
groupedResults = orderBy(groupedResults, 'instanceCount', 'desc')
}
return (
<>
<PerspectiveTabs
tabs={perspective.tabs}
screenSize={props.screenSize}
layoutConfig={layoutConfig}
/>
<Route
exact path={`${rootUrl}/${perspectiveID}/${searchMode}`}
render={() => <Redirect to={`${rootUrl}/${perspectiveID}/${searchMode}/table`} />}
/>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/table`}>
<VirtualizedTable
portalConfig={portalConfig}
list={Immutable.List(props.clientFSResults)}
clientFSState={props.clientFSState}
clientFSSortResults={props.clientFSSortResults}
perspectiveID={perspectiveID}
layoutConfig={layoutConfig}
/>
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/map_clusters`}>
<LeafletMap
portalConfig={portalConfig}
perspectiveConfig={perspective}
center={mapClusters.center}
zoom={mapClusters.zoom}
results={props.clientFSResults}
leafletMapState={props.leafletMapState}
resultClass='mapClusters'
pageType='clientFSResults'
mapMode='cluster'
createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
fetchResults={props.fetchResults}
fetchGeoJSONLayers={props.fetchGeoJSONLayers}
clearGeoJSONLayers={props.clearGeoJSONLayers}
fetchByURI={props.fetchByURI}
fetching={false}
showInstanceCountInClusters={false}
updateFacetOption={props.updateFacetOption}
showError={props.showError}
showExternalLayers
layerControlExpanded={layerControlExpanded}
layerConfigs={props.leafletConfig.layerConfigs}
updateMapBounds={props.updateMapBounds}
layoutConfig={layoutConfig}
/>
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/map_markers`}>
{props.clientFSResults.length < 500
? (
<LeafletMap
portalConfig={portalConfig}
perspectiveConfig={perspective}
center={mapMarkers.center}
zoom={mapMarkers.zoom}
results={props.clientFSResults}
leafletMapState={props.leafletMapState}
resultClass='mapMarkers'
pageType='clientFSResults'
mapMode='marker'
createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
fetchResults={props.fetchResults}
fetchGeoJSONLayers={props.fetchGeoJSONLayers}
clearGeoJSONLayers={props.clearGeoJSONLayers}
fetchByURI={props.fetchByURI}
fetching={false}
showInstanceCountInClusters={false}
updateFacetOption={props.updateFacetOption}
showError={props.showError}
showExternalLayers
layerControlExpanded={layerControlExpanded}
layerConfigs={props.leafletConfig.layerConfigs}
updateMapBounds={props.updateMapBounds}
layoutConfig={layoutConfig}
/>
)
: <ResultInfo message={intl.get('leafletMap.tooManyResults')} />}
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/statistics`}>
<ApexCharts
portalConfig={portalConfig}
layoutConfig={layoutConfig}
perspectiveConfig={props.perspectiveConfig}
apexChartsConfig={props.apexChartsConfig}
results={groupedResults}
pageType='clientFSResults'
facetUpdateID={props.clientFSState.facetUpdateID}
resultClassConfig={{
createChartData: 'createApexPieChartData',
property: props.clientFSState.groupBy,
title: {
text: props.clientFSState.groupByLabel,
align: 'left'
}
}}
/>
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/download`}>
<CSVButton
results={props.clientFSResults}
layoutConfig={layoutConfig}
portalConfig={portalConfig}
/>
</Route>
</>
)
}
Example #23
Source File: ObjectListCollapsible.js From sampo-ui with MIT License | 4 votes |
ObjectListCollapsible = props => {
const {
sortValues, sortBy, sortByConvertDataTypeTo, makeLink, externalLink, linkAsButton, columnId, showSource,
sourceExternalLink, numberedList, collapsedMaxWords, classes, shortenLabel
} = props
let { data } = props
const sortList = data => {
if (has(props, 'columnId') && props.columnId.endsWith('Timespan')) {
data = data.sort((a, b) => {
a = has(a, 'start') ? ISOStringToDate(a.start) : ISOStringToDate(a.end)
b = has(b, 'start') ? ISOStringToDate(b.start) : ISOStringToDate(b.end)
// arrange from the most recent to the oldest
return a > b ? 1 : a < b ? -1 : 0
})
} else if (props.columnId === 'event') {
data = orderBy(data, 'date')
} else if (props.sortBy) {
if (sortByConvertDataTypeTo && sortByConvertDataTypeTo === 'integer') {
data.forEach(item => {
item[sortBy] = parseInt(item[sortBy])
})
}
data = orderBy(data, sortBy)
} else {
data = orderBy(data, 'prefLabel')
}
return data
}
const renderItem = ({ addThreeDots, itemData, isFirstValue = false }) => {
if (columnId === 'event') {
return (
<>
<ObjectListItemEvent
data={itemData}
isFirstValue={isFirstValue}
/>
{addThreeDots &&
<span className={classes.threeDots} onClick={() => props.onExpandClick(props.rowId)}> ...</span>}
</>
)
} else {
return (
<>
<ObjectListItem
data={itemData}
shortenLabel={shortenLabel}
makeLink={makeLink}
externalLink={externalLink}
linkAsButton={linkAsButton}
isFirstValue={isFirstValue}
collapsedMaxWords={collapsedMaxWords}
/>
{addThreeDots &&
<span className={classes.threeDots} onClick={() => props.onExpandClick(props.rowId)}> ...</span>}
{showSource && itemData.source &&
<ObjectListItemSources
data={itemData.source}
shortenLabel={shortenLabel}
externalLink={sourceExternalLink}
/>}
</>
)
}
}
const renderListItems = data =>
<>
{data.map(item =>
<li key={item.id}>
{renderItem({ collapsed: false, itemData: item })}
</li>
)}
</>
const renderBulletedList = data =>
<ul className={classNames(classes.resultTableList, classes.valueList)}>
{renderListItems(data)}
</ul>
const renderNumberedList = data =>
<ol className={classes.resultTableList}>
{renderListItems(data)}
</ol>
if (data == null || data === '-') {
return '-'
} else if (Array.isArray(data)) {
data = sortValues ? sortList(data) : data
return (
<>
{!props.expanded && renderItem({ addThreeDots: true, itemData: data[0], isFirstValue: true })}
<Collapse in={props.expanded} timeout='auto' unmountOnExit>
{numberedList ? renderNumberedList(data) : renderBulletedList(data)}
</Collapse>
</>
)
} else {
return renderItem({ addThreeDots: shortenLabel, itemData: data })
}
}
Example #24
Source File: networkService.js From web-wallet with Apache License 2.0 | 4 votes |
async getTransferTypedData ({
utxos,
recipient,
value,
currency,
feeToken,
metadata
}) {
if (!utxos || !utxos.length) {
try {
const _utxos = await this.childChain.getUtxos(this.account);
utxos = orderBy(_utxos, i => i.amount, 'desc');
} catch (error) {
throw new WebWalletError({
originalError: error,
customErrorMessage: 'Could not fetch account utxos. Please try transfer again.',
reportToSentry: false,
reportToUi: true
});
}
}
const allFees = await this.fetchFees();
const feeInfo = allFees.find(i => i.currency === feeToken);
if (!feeInfo) {
throw new WebWalletError({
originalError: new Error(`${feeToken} is not a supported fee token.`),
customErrorMessage: `${feeToken} is not a supported fee token.`,
reportToSentry: false,
reportToUi: true
});
}
const isAddress = this.web3.utils.isAddress(recipient);
if (!isAddress) {
recipient = await this.web3.eth.ens.getAddress(recipient);
}
if (!recipient) {
throw new WebWalletError({
originalError: new Error('Not a valid ENS name.'),
customErrorMessage: 'Not a valid ENS name.',
reportToSentry: false,
reportToUi: true
});
}
try {
const payments = [ {
owner: recipient,
currency,
amount: new BN(value.toString())
} ];
const fee = {
currency: feeToken,
amount: new BN(feeInfo.amount.toString())
};
const txBody = OmgUtil.transaction.createTransactionBody({
fromAddress: this.account,
fromUtxos: utxos,
payments,
fee,
metadata: metadata || OmgUtil.transaction.NULL_METADATA
});
const typedData = OmgUtil.transaction.getTypedData(txBody, this.plasmaContractAddress);
return { txBody, typedData };
} catch (error) {
if (error.message.includes('Insufficient funds')) {
throw new WebWalletError({
originalError: error,
customErrorMessage: error.message,
reportToSentry: false,
reportToUi: true
});
}
if (error.message.includes('Inputs must be an array of size')) {
throw new WebWalletError({
originalError: error,
customErrorMessage: 'This transaction will require more than 4 UTXOs. Please merge some UTXOs then try again.',
reportToSentry: false,
reportToUi: true
});
}
throw new WebWalletError({
originalError: error,
customErrorMessage: 'Could not create the transaction. Please try again.',
reportToSentry: false,
reportToUi: true
});
}
}
Example #25
Source File: Transactions.js From web-wallet with Apache License 2.0 | 4 votes |
function Transactions () {
const dispatch = useDispatch();
const [ page, setPage ] = useState(1);
const [ searchHistory, setSearchHistory ] = useState('');
const loading = useSelector(selectLoading([ 'TRANSACTION/GETALL' ]));
const activeTab = useSelector(selectActiveHistoryTab, isEqual);
const unorderedTransactions = useSelector(selectChildchainTransactions, isEqual);
const transactions = orderBy(unorderedTransactions, i => i.block.timestamp, 'desc');
function renderStatus (utxo) {
if (utxo.status === 'Pending') {
return 'Pending';
}
const total = utxo.outputs.reduce((prev, curr) => {
if (curr.owner !== networkService.account) {
return prev.add(new BN(curr.amount));
}
return prev;
}, new BN(0));
return `${total.toString()}`;
}
const _transactions = transactions.filter(i => {
return i.txhash.includes(searchHistory) || i.metadata.toLowerCase().includes(searchHistory);
});
const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE);
const endingIndex = page * PER_PAGE;
const paginatedTransactions = _transactions.slice(startingIndex, endingIndex);
return (
<div className={styles.container}>
<div className={styles.header}>
<h2>History</h2>
<Input
icon
placeholder='Search history'
value={searchHistory}
onChange={i => {
setPage(1);
setSearchHistory(i.target.value.toLowerCase());
}}
className={styles.searchBar}
/>
</div>
<div className={styles.data}>
<div className={styles.section}>
<Tabs
onClick={tab => {
setPage(1);
dispatch(setActiveHistoryTab(tab));
}}
activeTab={activeTab}
tabs={[ 'Transactions', 'Deposits' ]}
/>
{activeTab === 'Transactions' && (
<div className={styles.transactions}>
<Pager
currentPage={page}
isLastPage={paginatedTransactions.length < PER_PAGE}
onClickNext={() => setPage(page + 1)}
onClickBack={() => setPage(page - 1)}
/>
{!paginatedTransactions.length && !loading && (
<div className={styles.disclaimer}>No transaction history.</div>
)}
{!paginatedTransactions.length && loading && (
<div className={styles.disclaimer}>Loading...</div>
)}
{paginatedTransactions.map((i, index) => {
return (
<Transaction
key={index}
link={
i.status === 'Pending'
? undefined
: `${config.blockExplorerUrl}/transaction/${i.txhash}`
}
title={`${truncate(i.txhash, 6, 4, '...')}`}
midTitle={i.metadata ? i.metadata : '-'}
subTitle={moment.unix(i.block.timestamp).format('lll')}
status={renderStatus(i)}
subStatus={`Block ${i.block.blknum}`}
/>
);
})}
</div>
)}
{activeTab === 'Deposits' && <Deposits searchHistory={searchHistory} />}
</div>
<Exits searchHistory={searchHistory} />
</div>
</div>
);
}
Example #26
Source File: TransferModal.js From web-wallet with Apache License 2.0 | 4 votes |
function TransferModal ({ open }) {
const dispatch = useDispatch();
const [ currency, setCurrency ] = useState('');
const [ value, setValue ] = useState('');
const [ feeToken, setFeeToken ] = useState('');
const [ recipient, setRecipient ] = useState('');
const [ metadata, setMetadata ] = useState('');
const [ usableFees, setUsableFees ] = useState([]);
const [ ledgerModal, setLedgerModal ] = useState(false);
const [ typedData, setTypedData ] = useState({});
const [ utxoPicker, setUtxoPicker ] = useState(false);
const [ utxos, setUtxos ] = useState([]);
const [ selectedUtxos, setSelectedUtxos ] = useState([]);
const [ selectedFeeUtxos, setSelectedFeeUtxos ] = useState([]);
const balances = useSelector(selectChildchainBalance, isEqual);
const fees = useSelector(selectFees, isEqual);
const ledgerConnect = useSelector(selectLedger);
const feesLoading = useSelector(selectLoading([ 'FEE/GET' ]));
const loading = useSelector(selectLoading([ 'TRANSFER/CREATE' ]));
useEffect(() => {
async function fetchUTXOS () {
const _utxos = await networkService.getUtxos();
const utxos = orderBy(_utxos, i => i.currency, 'desc');
setUtxos(utxos);
}
if (open) {
fetchUTXOS();
}
}, [ open ]);
useEffect(() => {
if (Object.keys(fees).length) {
const usableFees = balances.filter(balance => {
const feeObject = fees[balance.currency];
if (feeObject) {
if (new BN(balance.amount).gte(new BN(feeObject.amount))) {
return true;
}
}
return false;
}).map(i => {
const feeObject = fees[i.currency];
const feeAmount = new BN(feeObject.amount).div(new BN(feeObject.subunit_to_unit));
return {
title: i.name,
value: i.currency,
subTitle: `Fee Amount: ${feeAmount.toFixed()}`
};
});
setUsableFees(usableFees);
}
}, [ balances, fees, open ]);
useEffect(() => {
if (balances.length && !currency) {
setCurrency(balances[0].currency);
}
}, [ balances, currency, open ]);
useEffect(() => {
if (usableFees.length && !feeToken) {
setFeeToken(usableFees[0].value);
}
}, [ usableFees, feeToken ]);
const selectOptions = balances.map(i => ({
title: i.name,
value: i.currency,
subTitle: `Balance: ${logAmount(i.amount, i.decimals)}`
}));
async function submit ({ useLedgerSign }) {
if (
value > 0 &&
currency &&
feeToken &&
recipient
) {
try {
const valueTokenInfo = await getToken(currency);
const { txBody, typedData } = await dispatch(getTransferTypedData({
utxos: [ ...selectedUtxos, ...selectedFeeUtxos ],
recipient,
value: powAmount(value, valueTokenInfo.decimals),
currency,
feeToken,
metadata
}));
setTypedData(typedData);
const res = await dispatch(transfer({
useLedgerSign,
txBody,
typedData
}));
if (res) {
dispatch(setActiveHistoryTab('Transactions'));
dispatch(openAlert('Transfer submitted. You will be blocked from making further transactions until the transfer is confirmed.'));
handleClose();
}
} catch (err) {
//
}
}
}
function handleClose () {
setCurrency('');
setValue('');
setFeeToken('');
setRecipient('');
setSelectedUtxos([]);
setUtxos([]);
setUtxoPicker(false);
setMetadata('');
setLedgerModal(false);
dispatch(closeModal('transferModal'));
}
const disabledTransfer = value <= 0 ||
!currency ||
!feeToken ||
!recipient ||
new BN(value).gt(new BN(getMaxTransferValue()));
function getMaxTransferValue () {
const transferingBalanceObject = balances.find(i => i.currency.toLowerCase() === currency.toLowerCase());
if (!transferingBalanceObject) {
return;
}
if (currency.toLowerCase() === feeToken.toLowerCase()) {
const availableAmount = new BN(transferingBalanceObject.amount).minus(new BN(fees[feeToken.toLowerCase()].amount));
return logAmount(availableAmount, transferingBalanceObject.decimals);
}
return logAmount(transferingBalanceObject.amount, transferingBalanceObject.decimals);
}
function handleUtxoClick (utxo) {
const isSelected = selectedUtxos.some(i => i.utxo_pos === utxo.utxo_pos);
if (isSelected) {
return setSelectedUtxos(selectedUtxos.filter(i => i.utxo_pos !== utxo.utxo_pos));
}
if ((selectedUtxos.length + selectedFeeUtxos.length) < 4) {
return setSelectedUtxos([ ...selectedUtxos, utxo ]);
}
}
function handleFeeUtxoClick (utxo) {
const isSelected = selectedFeeUtxos.some(i => i.utxo_pos === utxo.utxo_pos);
if (isSelected) {
return setSelectedFeeUtxos(selectedFeeUtxos.filter(i => i.utxo_pos !== utxo.utxo_pos));
}
if ((selectedUtxos.length + selectedFeeUtxos.length) < 4) {
return setSelectedFeeUtxos([ ...selectedFeeUtxos, utxo ]);
}
}
function handleUtxoPickerBack () {
setSelectedUtxos([]);
setSelectedFeeUtxos([]);
setUtxoPicker(false);
}
function renderUtxoPicker () {
const currencyUtxos = utxos
.filter(i => i.currency.toLowerCase() === currency.toLowerCase())
.filter(i => !!i);
const feeUtxos = utxos
.filter(i => i.currency.toLowerCase() === feeToken.toLowerCase())
.filter(i => !!i);
const selectedCurrencyAmount = selectedUtxos.reduce((acc, cur) => {
return acc.plus(new BN(cur.amount.toString()));
}, new BN(0));
const selectedFeeAmount = selectedFeeUtxos.reduce((acc, cur) => {
return acc.plus(new BN(cur.amount.toString()));
}, new BN(0));
const currencyObject = balances.find(i => i.currency.toLowerCase() === currency.toLowerCase());
const currencyCoverAmount = new BN(powAmount(value.toString(), currencyObject.decimals));
const feeObject = fees[feeToken.toLowerCase()];
const feeCoverAmount = new BN(feeObject.amount.toString());
const sameCurrency = feeToken.toLowerCase() === currency.toLowerCase();
const utxoPickerDisabled = sameCurrency
? currencyCoverAmount.plus(feeCoverAmount).gt(selectedCurrencyAmount)
: currencyCoverAmount.gt(selectedCurrencyAmount) || feeCoverAmount.gt(selectedFeeAmount);
function renderCurrencyPick () {
const enough = sameCurrency
? currencyCoverAmount.plus(feeCoverAmount).lte(selectedCurrencyAmount)
: currencyCoverAmount.lte(selectedCurrencyAmount);
return (
<>
<div className={styles.description}>
Transfer amount to cover: {sameCurrency
? logAmount(currencyCoverAmount.plus(feeCoverAmount), currencyObject.decimals)
: logAmount(currencyCoverAmount, currencyObject.decimals)}
</div>
<div className={[ styles.list, !sameCurrency ? styles.doubleList : '' ].join(' ')}>
{!currencyUtxos.length && (
<div className={styles.disclaimer}>You do not have any UTXOs for this token on the OMG Network.</div>
)}
{currencyUtxos.map((i, index) => {
const selected = selectedUtxos.some(selected => selected.utxo_pos === i.utxo_pos);
return (
<div
key={index}
onClick={() => {
if (!enough || selected) {
handleUtxoClick(i);
}
}}
className={[
styles.utxo,
selected ? styles.selected : ''
].join(' ')}
>
<div className={styles.title}>
{i.tokenInfo.name}
</div>
<div className={styles.value}>
<div className={styles.amount}>
{logAmount(i.amount.toString(), i.tokenInfo.decimals)}
</div>
<div className={styles.check}>
{selected && <Check />}
</div>
</div>
</div>
);
})}
</div>
</>
);
}
function renderFeePick () {
const logFeeAmount = new BN(feeObject.amount.toString()).div(new BN(feeObject.subunit_to_unit.toString()));
const enough = selectedFeeAmount.gte(feeCoverAmount);
return (
<>
<div className={styles.description}>
Fee amount to cover: {logFeeAmount.toFixed()}
</div>
<div className={[ styles.list, !sameCurrency ? styles.doubleList : '' ].join(' ')}>
{!feeUtxos.length && (
<div className={styles.disclaimer}>You do not have any fee UTXOs on the OMG Network.</div>
)}
{feeUtxos.map((i, index) => {
const selected = selectedFeeUtxos.some(selected => selected.utxo_pos === i.utxo_pos);
return (
<div
key={index}
onClick={() => {
if (!enough || selected) {
handleFeeUtxoClick(i);
}
}}
className={[
styles.utxo,
selected ? styles.selected : ''
].join(' ')}
>
<div className={styles.title}>
{i.tokenInfo.name}
</div>
<div className={styles.value}>
<div className={styles.amount}>
{logAmount(i.amount.toString(), i.tokenInfo.decimals)}
</div>
<div className={styles.check}>
{selected && <Check />}
</div>
</div>
</div>
);
})}
</div>
</>
);
}
return (
<>
<h2>Select UTXOs</h2>
<div className={styles.description}>
By default, this wallet will automatically pick UTXOs to cover your transaction amount. However, if you are a more advanced user, you can pick the UTXOs you would like to spend in this transaction manually.
</div>
{renderCurrencyPick()}
{!sameCurrency && renderFeePick()}
<div className={styles.disclaimer}>You can select a maximum of 4 UTXOs.</div>
<div className={styles.buttons}>
<Button
onClick={handleUtxoPickerBack}
type='outline'
className={styles.button}
>
USE DEFAULT
</Button>
<Button
className={styles.button}
onClick={() => setUtxoPicker(false)}
type='primary'
disabled={utxoPickerDisabled}
>
SELECT UTXOS
</Button>
</div>
</>
);
}
function renderTransferScreen () {
return (
<>
<h2>Transfer</h2>
<div className={styles.address}>
{`From address : ${networkService.account}`}
</div>
<Input
label='To Address'
placeholder='Hash or ENS name'
paste
value={recipient}
onChange={i => setRecipient(i.target.value)}
/>
<InputSelect
label='Amount to transfer'
placeholder={0}
value={value}
onChange={i => {
setValue(i.target.value);
setSelectedUtxos([]);
setSelectedFeeUtxos([]);
}}
selectOptions={selectOptions}
onSelect={i => {
setCurrency(i.target.value);
setSelectedUtxos([]);
setSelectedFeeUtxos([]);
}}
selectValue={currency}
maxValue={getMaxTransferValue()}
/>
{value > 0 && (
<div
className={styles.utxoPickLink}
onClick={() => setUtxoPicker(true)}
>
{selectedUtxos.length ? 'Change Selected UTXOs' : 'Advanced UTXO Select'}
</div>
)}
<Select
loading={feesLoading}
label='Fee'
value={feeToken}
options={usableFees}
onSelect={i => {
setFeeToken(i.target.value);
setSelectedUtxos([]);
setSelectedFeeUtxos([]);
}}
error="No balance to pay fees"
/>
<Input
label='Message'
placeholder='-'
value={metadata}
onChange={i => setMetadata(i.target.value || '')}
/>
<div className={styles.buttons}>
<Button
onClick={handleClose}
type='outline'
className={styles.button}
>
CANCEL
</Button>
<Button
className={styles.button}
onClick={() => {
ledgerConnect
? setLedgerModal(true)
: submit({ useLedgerSign: false });
}}
type='primary'
loading={loading}
tooltip='Your transfer transaction is still pending. Please wait for confirmation.'
disabled={disabledTransfer}
>
{ledgerConnect ? 'TRANSFER WITH LEDGER' : 'TRANSFER'}
</Button>
</div>
</>
);
}
return (
<Modal open={open}>
{!ledgerModal && !utxoPicker && renderTransferScreen()}
{!ledgerModal && utxoPicker && renderUtxoPicker()}
{ledgerModal && (
<LedgerPrompt
loading={loading}
submit={submit}
handleClose={handleClose}
typedData={typedData}
/>
)}
</Modal>
);
}
Example #27
Source File: MergeModal.js From web-wallet with Apache License 2.0 | 4 votes |
function MergeModal ({ open }) {
const dispatch = useDispatch();
const [ selectedUTXOs, setSelectedUTXOs ] = useState([]);
const [ searchUTXO, setSearchUTXO ] = useState('');
const [ utxos, setUtxos ] = useState([]);
const [ ledgerModal, setLedgerModal ] = useState(false);
const [ typedData, setTypedData ] = useState({});
const loading = useSelector(selectLoading([ 'TRANSFER/CREATE' ]));
const ledgerConnect = useSelector(selectLedger);
useEffect(() => {
async function fetchUTXOS () {
const _utxos = await networkService.getUtxos();
const utxos = orderBy(_utxos, i => i.currency, 'desc');
setUtxos(utxos);
}
if (open) {
fetchUTXOS();
}
}, [ open ]);
useEffect(() => {
if (selectedUTXOs.length) {
setSearchUTXO(selectedUTXOs[0].currency);
const { typedData } = networkService.getMergeTypedData(selectedUTXOs);
setTypedData(typedData);
}
if (!selectedUTXOs.length) {
setSearchUTXO('');
}
}, [ selectedUTXOs ]);
async function submit ({ useLedgerSign }) {
if (selectedUTXOs.length > 1 && selectedUTXOs.length < 5) {
const res = await dispatch(mergeUtxos(useLedgerSign, selectedUTXOs));
if (res) {
dispatch(setActiveHistoryTab('Transactions'));
dispatch(openAlert('Merge submitted. You will be blocked from making further transactions until the merge is confirmed.'));
handleClose();
}
}
}
function handleClose () {
setSelectedUTXOs([]);
setSearchUTXO('');
setLedgerModal(false);
dispatch(closeModal('mergeModal'));
}
function handleUtxoClick (utxo) {
const isSelected = selectedUTXOs.some(i => i.utxo_pos === utxo.utxo_pos);
if (isSelected) {
setSelectedUTXOs(selectedUTXOs.filter(i => i.utxo_pos !== utxo.utxo_pos));
}
if (!isSelected && selectedUTXOs.length < 4) {
setSelectedUTXOs([ ...selectedUTXOs, utxo ]);
}
}
function renderMergeScreen () {
const _utxos = utxos
.filter(i => i.currency.includes(searchUTXO))
.filter(i => i);
return (
<>
<h2>Merge UTXOs</h2>
<div className={styles.disclaimer}>Select the UTXOs you want to merge</div>
<div className={styles.list}>
{!utxos.length && (
<div className={styles.disclaimer}>You do not have any UTXOs on the OMG Network.</div>
)}
{_utxos.map((i, index) => {
const selected = selectedUTXOs.some(selected => selected.utxo_pos === i.utxo_pos);
return (
<div
key={index}
onClick={() => handleUtxoClick(i)}
className={[
styles.utxo,
selected ? styles.selected : ''
].join(' ')}
>
<div className={styles.title}>
{i.tokenInfo.name}
</div>
<div className={styles.value}>
<div className={styles.amount}>
{logAmount(i.amount.toString(), i.tokenInfo.decimals)}
</div>
<div className={styles.check}>
{selected && <Check />}
</div>
</div>
</div>
);
})}
</div>
<div className={styles.disclaimer}>You can select a maximum of 4 UTXOs to merge at once.</div>
<div className={styles.buttons}>
<Button
onClick={handleClose}
type='outline'
className={styles.button}
>
CANCEL
</Button>
{ledgerConnect ? (
<Button
onClick={() => setLedgerModal(true)}
type='primary'
className={styles.button}
loading={loading}
tooltip='Your merge transaction is still pending. Please wait for confirmation.'
disabled={selectedUTXOs.length <= 1 || selectedUTXOs.length > 4}
>
MERGE WITH LEDGER
</Button>) : (
<Button
onClick={submit}
type='primary'
className={styles.button}
loading={loading}
tooltip='Your merge transaction is still pending. Please wait for confirmation.'
disabled={selectedUTXOs.length <= 1 || selectedUTXOs.length > 4}
>
MERGE
</Button>)}
</div>
</>
);
}
return (
<Modal open={open}>
{!ledgerModal && renderMergeScreen()}
{ledgerModal && (
<LedgerPrompt
loading={loading}
submit={submit}
handleClose={handleClose}
typedData={typedData}
/>
)}
</Modal>
);
}
Example #28
Source File: SelectStep.js From web-wallet with Apache License 2.0 | 4 votes |
function SelectStep ({
setSelectedUTXO,
selectedUTXO,
handleClose,
setStep,
gasPrice,
setGasPrice,
selectedSpeed,
setSelectedSpeed
}) {
const dispatch = useDispatch();
const [ utxos, setUtxos ] = useState([]);
const [ searchUTXO, setSearchUTXO ] = useState('');
const submitLoading = useSelector(selectLoading([
`QUEUE/GET_${selectedUTXO ? selectedUTXO.currency : ''}`,
'EXIT/CREATE'
]));
useEffect(() => {
async function fetchUTXOS () {
const _utxos = await networkService.getUtxos();
const utxos = orderBy(_utxos, i => i.currency, 'desc');
setUtxos(utxos);
}
fetchUTXOS();
}, []);
async function doCheckExitQueue () {
const res = await dispatch(checkForExitQueue(selectedUTXO.currency));
if (!res) {
return setStep(2);
}
return doExit();
}
async function doExit () {
const res = await dispatch(exitUtxo(selectedUTXO, gasPrice));
if (res) {
dispatch(openAlert('Exit submitted. You will be blocked from making further transactions until the exit is confirmed.'));
handleClose();
}
}
const _utxos = useMemo(() => {
return utxos.filter(i => {
return i.currency.toLowerCase().includes(searchUTXO.toLowerCase()) ||
i.tokenInfo.name.toLowerCase().includes(searchUTXO.toLowerCase());
}).filter(i => !!i);
}, [ utxos, searchUTXO ]);
function closeModal () {
setSearchUTXO('');
setSelectedSpeed('normal');
handleClose();
}
return (
<>
<h2>Start Standard Exit</h2>
<Input
label='Select a UTXO to exit from the OMG Network'
icon
placeholder='Search by token'
value={searchUTXO}
onChange={i => setSearchUTXO(i.target.value)}
/>
<div className={styles.list}>
{!utxos.length && (
<div className={styles.disclaimer}>You do not have any UTXOs on the OMG Network.</div>
)}
{_utxos.map((i, index) => {
return (
<div
key={index}
onClick={() => setSelectedUTXO(i)}
className={[
styles.utxo,
selectedUTXO === i ? styles.selected : ''
].join(' ')}
>
<div className={styles.title}>
{i.tokenInfo.name}
</div>
<div className={styles.value}>
<div className={styles.amount}>
{logAmount(i.amount.toString(), i.tokenInfo.decimals)}
</div>
<div className={styles.check}>
{selectedUTXO === i && <Check />}
</div>
</div>
</div>
);
})}
</div>
<GasPicker
selectedSpeed={selectedSpeed}
setSelectedSpeed={setSelectedSpeed}
setGasPrice={setGasPrice}
/>
<div className={styles.buttons}>
<Button
onClick={closeModal}
type='outline'
style={{ flex: 0 }}
>
CANCEL
</Button>
<Button
onClick={doCheckExitQueue}
type='primary'
style={{ flex: 0 }}
loading={submitLoading}
tooltip='Your exit transaction is still pending. Please wait for confirmation.'
disabled={!selectedUTXO}
>
SUBMIT EXIT
</Button>
</div>
</>
);
}
Example #29
Source File: MultiLinePlot.jsx From covince with MIT License | 4 votes |
MultiLinePlot = props => {
const {
activeLineages,
area_data,
chartZoom,
className,
darkMode,
date,
groupStackedColours = true,
height = 120,
parameter,
preset: deprecatedPreset,
setDate,
stroke = 'blueGray',
tooltipEnabled,
type,
width,
/* xAxis: xAxisConfig = {}, */
yAxis: yAxisConfig,
zoomEnabled
} = props
const preset = useMemo(() => {
if (parameter && parameter.format === 'percentage') return 'percentage'
// back compat
if (deprecatedPreset) return deprecatedPreset
if (parameter && parameter.id === 'p') return 'percentage'
return null
}, [parameter, deprecatedPreset])
const precision = useMemo(() => {
return parameter ? parameter.precision : undefined
}, [parameter])
const chart = useMemo(() => {
const dataByDate = {}
const lineageSum = {}
for (const d of area_data) {
if (d.parameter === parameter.id && d.lineage !== 'total') {
const next = {
...dataByDate[d.date],
date: d.date,
[d.lineage]: d.mean,
[`${d.lineage}_range`]: d.range
}
if (d.lineage in activeLineages && activeLineages[d.lineage].active) {
next.maxY = Math.max(next.maxY || 0, d.range[1] || d.mean)
next.sumY = (next.sumY || 0) + d.mean
}
dataByDate[d.date] = next
const sum = lineageSum[d.lineage] || 0
lineageSum[d.lineage] = (sum + d.mean)
}
}
const data =
orderBy(Object.values(dataByDate), 'date', 'asc')
.map((d, index) => ({ ...d, index }))
const dates = data.map(_ => _.date)
const lineages = []
for (const lineage of Object.keys(lineageSum)) {
const { active, colour } = activeLineages[lineage]
if (active) {
lineages.push({ lineage, colour, average: lineageSum[lineage] / dates.length })
}
}
const ordered = orderBy(lineages, 'average', 'asc')
let sorted
if (groupStackedColours) {
sorted = []
while (ordered.length > 0) {
const [item] = ordered.splice(0, 1)
if (sorted.includes(item)) continue
sorted.push(item)
for (let i = 0; i < ordered.length; i++) {
const other = ordered[i]
if (item.colour === other.colour) {
sorted.push(other)
}
}
}
} else {
sorted = ordered
}
return {
lineages: sorted,
data,
dates
}
}, [area_data, activeLineages, groupStackedColours])
const { data, dates } = chart
const chartProps = useMemo(() => ({
width,
height,
margin: { top: 12, left: 0, right: 24 }
}), [width, height])
const { dateRange, setChartZoom, clearChartZoom } = chartZoom
const xAxisDomain = useMemo(() => {
const minIndex = 0
const maxIndex = data.length - 1
if (dateRange && dates.length) {
const [minDate, maxDate] = dateRange
const min = minDate ? Math.max(dates.indexOf(minDate), minIndex) : minIndex
let max = maxDate ? dates.indexOf(maxDate) : maxIndex
if (max === -1) max = maxIndex
return min < max ? [min, max] : [max, min]
}
return [minIndex, maxIndex]
}, [dateRange, dates])
const xAxisProps = useMemo(() => {
const indices = Object.keys(dates)
let ticks = indices
if (dateRange) {
const [minIndex, maxIndex] = xAxisDomain
ticks = indices.slice(minIndex, maxIndex + 1)
}
return {
allowDataOverflow: true,
dataKey: 'index',
domain: xAxisDomain,
ticks,
type: 'number'
}
}, [xAxisDomain, dates])
const [zoomArea, setZoomArea] = React.useState({})
const [isHovering, setIsHovering] = React.useState(false)
const eventHandlers = useMemo(() => {
const clickHandlers = {
onClick: item => {
if (date && item && !zoomArea.dragged) { // do not set date if not visible on chart
setDate(data[item.activeLabel].date)
}
if (zoomEnabled) {
setZoomArea({ dragged: zoomArea.dragged })
}
},
onMouseDown: e => {
if (e && zoomEnabled) {
setZoomArea({ start: e.activeLabel, end: e.activeLabel, dragged: false })
}
},
onMouseMove: e => {
if (e) {
setIsHovering(e.activeLabel !== undefined)
if (zoomArea.start === undefined) return
let end = e.activeLabel
if (e.activeLabel === undefined) { // outside of axes
end = xAxisDomain[zoomArea.end >= data.length / 2 ? 1 : 0]
}
setZoomArea({ start: zoomArea.start, end, dragged: true })
}
},
onMouseLeave: e => {
setIsHovering(false)
},
onMouseUp: (_, e) => {
if (zoomArea.end !== zoomArea.start) {
const xStart = data[zoomArea.start].date
const xEnd = data[zoomArea.end].date
const args = xStart < xEnd ? [xStart, xEnd] : [xEnd, xStart]
setChartZoom(...args)
}
setZoomArea({ dragged: zoomArea.dragged })
}
}
if (!tooltipEnabled) { // touch handlers need to be replaced when tooltip is missing
return {
...clickHandlers,
onTouchStart: clickHandlers.onMouseDown,
onTouchMove: clickHandlers.onMouseMove,
onTouchEnd: clickHandlers.onMouseUp
}
}
return clickHandlers
}, [zoomEnabled, data, zoomArea, isHovering])
const cursor = useMemo(() => {
if (zoomArea.start) return 'ew-resize'
if (isHovering) return 'crosshair'
return undefined
}, [zoomArea, isHovering])
return (
<div
className={classNames('relative select-none focus:outline-none', className)}
onDoubleClick={clearChartZoom}
>
<MainChart
{...{
...chartProps,
...eventHandlers,
activeLineages,
chart,
dateRange,
cursor,
darkMode,
precision,
preset,
stroke,
tooltipEnabled,
type,
xAxisProps,
yAxisConfig,
zoomArea
}}
/>
<div className='absolute top-0 left-0 pointer-events-none'>
<ComposedChart {...chartProps} data={data}>
<XAxis
{...xAxisProps}
tick={false}
stroke='none'
/>
<YAxis
width={48}
tick={false}
stroke='none'
/>
<ReferenceLine
x={dates.indexOf(date)}
stroke={tailwindColors[stroke][darkMode ? 300 : 400]}
label=''
strokeWidth={2}
style={{ mixBlendMode: darkMode ? 'screen' : 'multiply' }}
/>
</ComposedChart>
</div>
</div>
)
}