mirror of https://gitlab.com/ecentrics/concordia
Apostolos Fanakis
7 years ago
21 changed files with 623 additions and 512 deletions
@ -1,5 +1,4 @@ |
|||
body { |
|||
margin: 0; |
|||
padding: 0; |
|||
font-family: sans-serif; |
|||
} |
|||
|
@ -0,0 +1,108 @@ |
|||
/* Progress Bar */ |
|||
|
|||
.progress-bar-container { |
|||
position: absolute; |
|||
top: 54px; |
|||
left: 0px; |
|||
width: 100%; |
|||
} |
|||
|
|||
.progress { |
|||
position: relative; |
|||
height: 4px; |
|||
display: block; |
|||
width: 100%; |
|||
background-color: #acece6; |
|||
border-radius: 2px; |
|||
background-clip: padding-box; |
|||
margin: 0.5rem 0 1rem 0; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.progress .indeterminate { |
|||
background-color: #00b5ad; |
|||
} |
|||
|
|||
.progress .indeterminate:before { |
|||
content: ''; |
|||
position: absolute; |
|||
background-color: inherit; |
|||
top: 0; |
|||
left: 0; |
|||
bottom: 0; |
|||
will-change: left, right; |
|||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite; |
|||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite; |
|||
} |
|||
|
|||
.progress .indeterminate:after { |
|||
content: ''; |
|||
position: absolute; |
|||
background-color: inherit; |
|||
top: 0; |
|||
left: 0; |
|||
bottom: 0; |
|||
will-change: left, right; |
|||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite; |
|||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite; |
|||
-webkit-animation-delay: 1.15s; |
|||
animation-delay: 1.15s; |
|||
} |
|||
|
|||
@-webkit-keyframes indeterminate { |
|||
0% { |
|||
left: -35%; |
|||
right: 100%; |
|||
} |
|||
60% { |
|||
left: 100%; |
|||
right: -90%; |
|||
} |
|||
100% { |
|||
left: 100%; |
|||
right: -90%; |
|||
} |
|||
} |
|||
|
|||
@keyframes indeterminate { |
|||
0% { |
|||
left: -35%; |
|||
right: 100%; |
|||
} |
|||
60% { |
|||
left: 100%; |
|||
right: -90%; |
|||
} |
|||
100% { |
|||
left: 100%; |
|||
right: -90%; |
|||
} |
|||
} |
|||
@-webkit-keyframes indeterminate-short { |
|||
0% { |
|||
left: -200%; |
|||
right: 100%; |
|||
} |
|||
60% { |
|||
left: 107%; |
|||
right: -8%; |
|||
} |
|||
100% { |
|||
left: 107%; |
|||
right: -8%; |
|||
} |
|||
} |
|||
@keyframes indeterminate-short { |
|||
0% { |
|||
left: -200%; |
|||
right: 100%; |
|||
} |
|||
60% { |
|||
left: 107%; |
|||
right: -8%; |
|||
} |
|||
100% { |
|||
left: 107%; |
|||
right: -8%; |
|||
} |
|||
} |
@ -0,0 +1,172 @@ |
|||
import React, { Component } from 'react'; |
|||
import { drizzleConnect } from 'drizzle-react'; |
|||
import PropTypes from 'prop-types'; |
|||
|
|||
import { Message } from 'semantic-ui-react'; |
|||
|
|||
import { updateTransaction } from '../redux/actions/transactionsMonitorActions'; |
|||
|
|||
class RightSideBar extends Component { |
|||
constructor(props, context) { |
|||
super(props); |
|||
|
|||
this.handleMessageDismiss = this.handleMessageDismiss.bind(this); |
|||
|
|||
this.drizzle = context.drizzle; |
|||
this.transactionsStackIds = []; |
|||
this.transactionsTxHashes = []; |
|||
|
|||
this.state = { |
|||
transactionsCompletionTime: [], |
|||
isTransactionMessageActive: [] |
|||
} |
|||
} |
|||
|
|||
handleMessageDismiss(messageIndex) { |
|||
let isTransactionMessageActiveShallowCopy = this.state.isTransactionMessageActive.slice(); |
|||
isTransactionMessageActiveShallowCopy[messageIndex] = false; |
|||
this.setState({ |
|||
isTransactionMessageActive: isTransactionMessageActiveShallowCopy |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
let transactionMessages = this.props.transactionsQueue.map((transaction, index) => { |
|||
if (!this.state.isTransactionMessageActive[index]){ |
|||
return null; |
|||
} |
|||
let color = 'black'; |
|||
let message = []; |
|||
|
|||
while(true) { |
|||
if (transaction.status === 'initialized') break; |
|||
message.push("New transaction has been queued and is waiting your confirmation."); |
|||
|
|||
if (transaction.status === 'acceptance_pending') break; |
|||
message.push(<br key="confirmed"/>); |
|||
message.push("- transaction confirmed"); |
|||
|
|||
if (transaction.status === 'mining_pending') break; |
|||
message.push(<br key="mined"/>); |
|||
message.push("- transaction mined"); |
|||
|
|||
if (transaction.status === 'success') { |
|||
color = 'green'; |
|||
message.push(<br key="success"/>); |
|||
message.push("- transaction completed successfully"); |
|||
break; |
|||
} |
|||
if (transaction.status === 'error') { |
|||
color = 'red'; |
|||
message.push(<br key="fail"/>); |
|||
message.push("Transaction failed to complete!"); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<div className="sidebar-message" key={index}> |
|||
<Message color={color} onDismiss={() => {this.handleMessageDismiss(index)}}> |
|||
{message} |
|||
</Message> |
|||
</div> |
|||
); |
|||
}); |
|||
|
|||
return (transactionMessages); |
|||
} |
|||
|
|||
componentDidUpdate(){ |
|||
for (var index = 0; index < this.props.transactionsQueue.length; ++index) { |
|||
let transaction = this.props.transactionsQueue[index]; |
|||
|
|||
if (transaction.status === 'initialized' && |
|||
this.transactionsStackIds[index] === undefined){ |
|||
/* User submitted a new transaction */ |
|||
|
|||
let isTransactionMessageActiveShallowCopy = this.state |
|||
.isTransactionMessageActive.slice(); |
|||
isTransactionMessageActiveShallowCopy[index] = true; |
|||
this.setState({ |
|||
isTransactionMessageActive: isTransactionMessageActiveShallowCopy |
|||
}); |
|||
|
|||
this.transactionsStackIds[index] = (this.drizzle |
|||
.contracts[transaction.contract] |
|||
.methods[transaction.method] |
|||
.cacheSend(...(transaction.params))); |
|||
this.props.store.dispatch(updateTransaction(index, { |
|||
status: 'acceptance_pending' |
|||
})); |
|||
} else if (transaction.status === 'acceptance_pending'){ |
|||
if (this.props.transactionStack[this.transactionsStackIds[index]]){ |
|||
/* User confirmed the transaction */ |
|||
|
|||
//Gets transaciton's hash
|
|||
this.transactionsTxHashes[index] = (this.props |
|||
.transactionStack[this.transactionsStackIds[index]]); |
|||
this.props.store.dispatch(updateTransaction(index, { |
|||
status: 'mining_pending' |
|||
})); |
|||
} |
|||
} else if (transaction.status === 'mining_pending'){ |
|||
if (this.props.transactions[this.transactionsTxHashes[index]] |
|||
.status === "success"){ |
|||
/* Transaction completed successfully */ |
|||
|
|||
//Gets returned data by contract
|
|||
let data = this.props.transactions[this.transactionsTxHashes[index]] |
|||
.receipt.events[transaction.event].returnValues; |
|||
|
|||
this.props.store.dispatch(updateTransaction(index, { |
|||
status: 'success', |
|||
returnData: data |
|||
})); |
|||
|
|||
let transactionsCompletionTimeShallowCopy = this.state |
|||
.transactionsCompletionTime.slice(); |
|||
transactionsCompletionTimeShallowCopy[index] = new Date().getTime(); |
|||
this.setState({ |
|||
transactionsCompletionTime: transactionsCompletionTimeShallowCopy |
|||
}); |
|||
if (this.props.transactionsQueue[index].callback){ |
|||
this.props.transactionsQueue[index].callback(data); |
|||
} |
|||
} else if (this.props.transactions[this.transactionsTxHashes[index]] |
|||
.status === "error"){ |
|||
/* Transaction failed to complete */ |
|||
|
|||
this.props.store.dispatch(updateTransaction(index, { |
|||
status: 'error' |
|||
})); |
|||
|
|||
let transactionsCompletionTimeShallowCopy = this.state |
|||
.transactionsCompletionTime.slice(); |
|||
transactionsCompletionTimeShallowCopy[index] = new Date().getTime(); |
|||
this.setState({ |
|||
transactionsCompletionTime: transactionsCompletionTimeShallowCopy |
|||
}); |
|||
if (this.props.transactionsQueue[index].callback){ |
|||
this.props.transactionsQueue[index].callback(null); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
RightSideBar.contextTypes = { |
|||
drizzle: PropTypes.object |
|||
}; |
|||
|
|||
const mapStateToProps = state => { |
|||
return { |
|||
transactionsQueue: state.transactionsQueue.transactions, |
|||
transactions: state.transactions, |
|||
transactionStack: state.transactionStack |
|||
} |
|||
}; |
|||
|
|||
const RightSideBarContainer = drizzleConnect(RightSideBar, mapStateToProps); |
|||
|
|||
export default RightSideBarContainer; |
@ -0,0 +1,54 @@ |
|||
//Action creators
|
|||
|
|||
export const INIT_TRANSACTION = 'INIT_TRANSACTION'; |
|||
export const UPDATE_TRANSACTION = 'UPDATE_TRANSACTION'; |
|||
|
|||
export function updateUsername(newUsername, callback){ |
|||
return { |
|||
type: INIT_TRANSACTION, |
|||
transactionDescriptor: |
|||
{ |
|||
contract: 'Forum', |
|||
method: 'updateUsername', |
|||
params: [newUsername], |
|||
event: 'UsernameUpdated', |
|||
}, |
|||
callback: callback |
|||
}; |
|||
} |
|||
|
|||
export function createTopic(callback){ |
|||
return { |
|||
type: INIT_TRANSACTION, |
|||
transactionDescriptor: |
|||
{ |
|||
contract: 'Forum', |
|||
method: 'createTopic', |
|||
params: [], |
|||
event: 'TopicCreated', |
|||
}, |
|||
callback: callback |
|||
}; |
|||
} |
|||
|
|||
export function createPost(topicID, callback){ |
|||
return { |
|||
type: INIT_TRANSACTION, |
|||
transactionDescriptor: |
|||
{ |
|||
contract: 'Forum', |
|||
method: 'createPost', |
|||
params: [topicID], |
|||
event: 'PostCreated', |
|||
}, |
|||
callback: callback |
|||
}; |
|||
} |
|||
|
|||
export function updateTransaction(transactionIndex, updateDescriptor){ |
|||
return { |
|||
type: UPDATE_TRANSACTION, |
|||
index: transactionIndex, |
|||
transactionUpdates: updateDescriptor |
|||
}; |
|||
} |
@ -0,0 +1,12 @@ |
|||
//Action creators
|
|||
|
|||
export const SHOW_PROGRESS_BAR = 'SHOW_PROGRESS_BAR'; |
|||
export const HIDE_PROGRESS_BAR = 'HIDE_PROGRESS_BAR'; |
|||
|
|||
export function showProgressBar(){ |
|||
return { type: 'SHOW_PROGRESS_BAR'}; |
|||
} |
|||
|
|||
export function hideProgressBar(){ |
|||
return { type: 'HIDE_PROGRESS_BAR'}; |
|||
} |
@ -0,0 +1,39 @@ |
|||
import { INIT_TRANSACTION, UPDATE_TRANSACTION } from '../actions/transactionsMonitorActions'; |
|||
|
|||
const initialState = { |
|||
transactions: [] |
|||
}; |
|||
|
|||
const transactionsReducer = (state = initialState, action) => { |
|||
switch (action.type) { |
|||
case INIT_TRANSACTION: |
|||
let transactionsShallowCopy = state.transactions.slice(); |
|||
transactionsShallowCopy.push({ |
|||
status: 'initialized', |
|||
contract: action.transactionDescriptor.contract, |
|||
method: action.transactionDescriptor.method, |
|||
params: action.transactionDescriptor.params, |
|||
event: action.transactionDescriptor.event, |
|||
returnData: null, |
|||
callback: action.callback |
|||
}); |
|||
return { |
|||
transactions: transactionsShallowCopy |
|||
}; |
|||
case UPDATE_TRANSACTION: |
|||
return { transactions: state.transactions.map( (transaction, index) => { |
|||
if (index !== action.index){ |
|||
return transaction; |
|||
} |
|||
|
|||
return { |
|||
...transaction, |
|||
...action.transactionUpdates |
|||
} |
|||
})}; |
|||
default: |
|||
return state; |
|||
} |
|||
}; |
|||
|
|||
export default transactionsReducer; |
@ -0,0 +1,22 @@ |
|||
import { SHOW_PROGRESS_BAR, HIDE_PROGRESS_BAR } from '../actions/userInterfaceActions'; |
|||
|
|||
const initialState = { |
|||
displayProgressBar: false |
|||
}; |
|||
|
|||
const userInterfaceReducer = (state = initialState, action) => { |
|||
switch (action.type) { |
|||
case SHOW_PROGRESS_BAR: |
|||
return { |
|||
displayProgressBar: true |
|||
}; |
|||
case HIDE_PROGRESS_BAR: |
|||
return { |
|||
displayProgressBar: false |
|||
}; |
|||
default: |
|||
return state; |
|||
} |
|||
}; |
|||
|
|||
export default userInterfaceReducer; |
Loading…
Reference in new issue