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 { |
body { |
||||
margin: 0; |
margin: 0; |
||||
padding: 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