From bdba1d7ea4e2d2e41618b7b24708515b63e89468 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Mon, 17 Jun 2019 17:54:12 +0300 Subject: [PATCH 01/51] temp --- dapp/package.json | 9 ++++--- dapp/src/actions/accounts.js | 4 +++ dapp/src/components/common/SignIn/index.jsx | 25 +++++++++++++++++++ .../containers/MainDashboard/index.jsx | 2 ++ .../dashboard/pages/Users/index.jsx | 4 +-- dapp/src/sagas/accounts.js | 18 ++++++++++--- dapp/src/services/3box.js | 0 dapp/src/services/web3.js | 11 ++++++++ 8 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 dapp/src/components/common/SignIn/index.jsx create mode 100644 dapp/src/services/3box.js diff --git a/dapp/package.json b/dapp/package.json index adb7b30a..837b78fc 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -28,6 +28,10 @@ ] }, "dependencies": { + "3box": "^1.9.0", + "@fuse/entities-contracts": "../contracts/entities/", + "@fuse/roles": "../packages/roles", + "@fuse/token-factory-contracts": "../contracts/token-factory/", "babel-core": "^6.26.3", "babel-eslint": "^8.2.3", "babel-loader": "^7.1.4", @@ -75,10 +79,7 @@ "webpack": "^4.6.0", "webpack-cli": "^3.1.2", "websocket": "^1.0.28", - "yup": "^0.27.0", - "@fuse/token-factory-contracts": "../contracts/token-factory/", - "@fuse/entities-contracts": "../contracts/entities/", - "@fuse/roles": "../packages/roles" + "yup": "^0.27.0" }, "devDependencies": { "chai": "^4.1.2", diff --git a/dapp/src/actions/accounts.js b/dapp/src/actions/accounts.js index fb4e7499..e3d115b1 100644 --- a/dapp/src/actions/accounts.js +++ b/dapp/src/actions/accounts.js @@ -11,6 +11,8 @@ export const FETCH_BALANCES = createRequestTypes('FETCH_BALANCES') export const FETCH_TOKENS_WITH_BALANCES = createRequestTypes('FETCH_TOKENS_WITH_BALANCES') export const ADD_USER = createRequestTypes('ADD_USER') +export const SIGN_IN = createRequestTypes('SIGN_IN') + export const balanceOfToken = (tokenAddress, accountAddress, options) => action(BALANCE_OF_TOKEN.REQUEST, { tokenAddress, accountAddress, options }) export const balanceOfNative = (accountAddress) => action(BALANCE_OF_NATIVE.REQUEST, { accountAddress }) export const balanceOfCln = (accountAddress) => action(BALANCE_OF_CLN.REQUEST, { accountAddress }) @@ -18,3 +20,5 @@ export const balanceOfCln = (accountAddress) => action(BALANCE_OF_CLN.REQUEST, { export const fetchBalances = (tokens, accountAddress) => action(FETCH_BALANCES.REQUEST, { accountAddress, tokens }) export const fetchTokensWithBalances = (accountAddress) => action(FETCH_TOKENS_WITH_BALANCES.REQUEST, { accountAddress }) export const fetchCommunities = (accountAddress) => communitiesAction(FETCH_COMMUNITIES.REQUEST, { accountAddress }) + +export const signIn = (accountAddress) => action(SIGN_IN.REQUEST, { accountAddress }) diff --git a/dapp/src/components/common/SignIn/index.jsx b/dapp/src/components/common/SignIn/index.jsx new file mode 100644 index 00000000..38924efa --- /dev/null +++ b/dapp/src/components/common/SignIn/index.jsx @@ -0,0 +1,25 @@ +import { Component } from 'react' +import { connect } from 'react-redux' +// import Box from '3box' +import { signIn } from 'actions/accounts' + +class SignInLayout extends Component { + componentDidMount = () => { + this.props.signIn(this.props.accountAddress) + } + + render = () => null +} + +// const mapStateToProps = (state) => ({ +// accountAddress: getAccountAddress(state) +// }) + +const mapDispatchToProps = { + signIn +} + +export default connect( + undefined, + mapDispatchToProps +)(SignInLayout) diff --git a/dapp/src/components/dashboard/containers/MainDashboard/index.jsx b/dapp/src/components/dashboard/containers/MainDashboard/index.jsx index f0d1a169..9a687a3b 100644 --- a/dapp/src/components/dashboard/containers/MainDashboard/index.jsx +++ b/dapp/src/components/dashboard/containers/MainDashboard/index.jsx @@ -19,6 +19,7 @@ import NavBar from 'components/common/NavBar' import { getAccountAddress } from 'selectors/accounts' import { checkIsAdmin } from 'selectors/entities' import { fetchEntities } from 'actions/communityEntities' +import SignIn from 'components/common/SignIn' class DashboardLayout extends PureComponent { state = { @@ -78,6 +79,7 @@ class DashboardLayout extends PureComponent { const { isClosed } = community return (
+ {accountAddress ? : undefined}
{ !isMobile diff --git a/dapp/src/components/dashboard/pages/Users/index.jsx b/dapp/src/components/dashboard/pages/Users/index.jsx index 538d08e9..88a728ca 100644 --- a/dapp/src/components/dashboard/pages/Users/index.jsx +++ b/dapp/src/components/dashboard/pages/Users/index.jsx @@ -275,12 +275,12 @@ class Users extends Component {

Users list

{ - isAdmin && ( + ( ) } diff --git a/dapp/src/sagas/accounts.js b/dapp/src/sagas/accounts.js index a65509bb..00ace473 100644 --- a/dapp/src/sagas/accounts.js +++ b/dapp/src/sagas/accounts.js @@ -6,7 +6,7 @@ import { getAddress, getNetworkType, getNetworkSide } from 'selectors/network' import { CHECK_ACCOUNT_CHANGED } from 'actions/network' import { TRANSFER_TOKEN, MINT_TOKEN, BURN_TOKEN } from 'actions/token' import { fetchTokenList } from 'sagas/token' -import web3 from 'services/web3' +import web3, { get3box } from 'services/web3' import { getContract } from 'services/contract' import { getAccountAddress } from 'selectors/accounts' import { fetchCommunities as fetchCommunitiesApi } from 'services/api/entities' @@ -56,6 +56,19 @@ function * fetchTokensWithBalances ({ accountAddress }) { yield call(fetchBalances, { accountAddress, tokens, networkSide }) } +const fetchCommunities = createEntitiesFetch(actions.FETCH_COMMUNITIES, fetchCommunitiesApi) + +function * signIn ({ accountAddress }) { + yield call(get3box, { accountAddress }) + + yield put({ type: actions.SIGN_IN.SUCCESS, + accountAddress, + response: { + accountAddress + } + }) +} + function * watchAccountChanged ({ response }) { yield put(actions.balanceOfCln(response.accountAddress)) } @@ -65,8 +78,6 @@ function * watchBalanceOfToken ({ response }) { yield put(actions.balanceOfToken(response.tokenAddress, accountAddress)) } -const fetchCommunities = createEntitiesFetch(actions.FETCH_COMMUNITIES, fetchCommunitiesApi) - export default function * accountsSaga () { yield all([ tryTakeEvery(actions.BALANCE_OF_TOKEN, balanceOfToken), @@ -76,6 +87,7 @@ export default function * accountsSaga () { tryTakeEvery(actions.FETCH_COMMUNITIES, fetchCommunities), takeEvery([TRANSFER_TOKEN.SUCCESS, BURN_TOKEN.SUCCESS, MINT_TOKEN.SUCCESS], watchBalanceOfToken), tryTakeEvery(actions.FETCH_BALANCES, fetchBalances, 1), + tryTakeEvery(actions.SIGN_IN, signIn, 1), tryTakeEvery(actions.FETCH_TOKENS_WITH_BALANCES, fetchTokensWithBalances, 1) ]) } diff --git a/dapp/src/services/3box.js b/dapp/src/services/3box.js new file mode 100644 index 00000000..e69de29b diff --git a/dapp/src/services/web3.js b/dapp/src/services/web3.js index c2e668d6..f793dbc6 100644 --- a/dapp/src/services/web3.js +++ b/dapp/src/services/web3.js @@ -1,4 +1,5 @@ import Web3 from 'web3' +import Box from '3box' import { isFuse, getProviderUrl } from 'utils/network' import { loadState } from 'utils/storage' @@ -17,6 +18,16 @@ export const getWeb3 = ({ bridgeType } = {}) => { return web3 } +let box = null + +export function * get3box ({ accountAddress }) { + if (box && box._web3provider.selectedAddress === accountAddress) { + return box + } + box = yield Box.openBox(accountAddress, Web3.givenProvider) + return box +} + const networkState = loadState('state.network') || CONFIG.web3.bridge.network const { foreignNetwork } = networkState From 6bb2639a931b42f0c66f975a126062c1a3b06087 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 19 Jun 2019 14:42:29 +0300 Subject: [PATCH 02/51] adding user data to 3box --- dapp/src/actions/communityEntities.js | 2 + .../containers/MainDashboard/index.jsx | 2 +- .../dashboard/pages/Users/index.jsx | 15 ++++-- dapp/src/sagas/commuityEntities.js | 49 +++++++++---------- dapp/src/sagas/metadata.js | 28 ++++++++--- dapp/src/services/api/entities.js | 4 +- dapp/src/utils/3box.js | 29 +++++++++++ 7 files changed, 91 insertions(+), 38 deletions(-) create mode 100644 dapp/src/utils/3box.js diff --git a/dapp/src/actions/communityEntities.js b/dapp/src/actions/communityEntities.js index 9d839565..8f3280e0 100644 --- a/dapp/src/actions/communityEntities.js +++ b/dapp/src/actions/communityEntities.js @@ -17,6 +17,7 @@ export const REMOVE_ADMIN_ROLE = createTransactionRequestTypes('REMOVE_ADMIN_ROL export const CONFIRM_USER = createTransactionRequestTypes('CONFIRM_USER') export const FETCH_ENTITY = createRequestTypes('FETCH_ENTITY') +export const JOIN_COMMUNITY = createRequestTypes('JOIN_COMMUNITY') export const fetchEntities = (communityAddress) => entitiesAction(FETCH_USERS_ENTITIES.REQUEST, { communityAddress }) export const fetchUsersEntities = (communityAddress, entityType = 'user') => entitiesAction(FETCH_USERS_ENTITIES.REQUEST, { communityAddress, entityType }) @@ -30,5 +31,6 @@ export const addAdminRole = (account) => action(ADD_ADMIN_ROLE.REQUEST, { accoun export const removeAdminRole = (account) => action(REMOVE_ADMIN_ROLE.REQUEST, { account }) export const confirmUser = (account) => action(CONFIRM_USER.REQUEST, { account }) export const editEntity = (listAddress, hash, data) => action(EDIT_ENTITY.REQUEST, { listAddress, hash, data }) +export const joinCommunity = (communityAddress, data) => action(JOIN_COMMUNITY.REQUEST, { communityAddress, data }) export const toggleCommunityMode = (communityAddress, isClosed) => action(TOGGLE_COMMUNITY_MODE.REQUEST, { communityAddress, isClosed }) diff --git a/dapp/src/components/dashboard/containers/MainDashboard/index.jsx b/dapp/src/components/dashboard/containers/MainDashboard/index.jsx index 9a687a3b..b6a72b41 100644 --- a/dapp/src/components/dashboard/containers/MainDashboard/index.jsx +++ b/dapp/src/components/dashboard/containers/MainDashboard/index.jsx @@ -73,7 +73,7 @@ class DashboardLayout extends PureComponent { return null } const { open } = this.state - const { match, token, community, metadata, networkType, communityAddress } = this.props + const { match, token, community, metadata, networkType, communityAddress, accountAddress } = this.props const { address: tokenAddress, name } = token const { isClosed } = community diff --git a/dapp/src/components/dashboard/pages/Users/index.jsx b/dapp/src/components/dashboard/pages/Users/index.jsx index 88a728ca..628b9705 100644 --- a/dapp/src/components/dashboard/pages/Users/index.jsx +++ b/dapp/src/components/dashboard/pages/Users/index.jsx @@ -13,7 +13,8 @@ import { addAdminRole, removeAdminRole, confirmUser, - toggleCommunityMode + toggleCommunityMode, + joinCommunity } from 'actions/communityEntities' import { fetchCommunity } from 'actions/token' import { loadModal, hideModal } from 'actions/ui' @@ -81,10 +82,15 @@ class Users extends Component { this.props.onlyOnFuse(this.loadAddUserModal) } - loadAddUserModal = () => { + handleJoinCommunity = () => { + this.props.onlyOnFuse(() => this.loadAddUserModal(true)) + } + + loadAddUserModal = (isJoin) => { + const submitEntity = isJoin ? this.props.joinCommunity : this.props.addEntity const { loadModal } = this.props loadModal(ADD_USER_MODAL, { - submitEntity: (data) => this.props.addEntity(this.props.community.communityAddress, { ...data, type: 'user' }, this.props.isClosed) + submitEntity: (data) => submitEntity(this.props.community.communityAddress, { ...data, type: 'user' }, this.props.isClosed) }) } @@ -277,7 +283,7 @@ class Users extends Component { { (
- + {isAdmin ? 'Add new user' : 'Join'} @@ -324,6 +330,7 @@ const mapStateToProps = (state) => ({ }) const mapDispatchToProps = { + joinCommunity, addEntity, confirmUser, addAdminRole, diff --git a/dapp/src/sagas/commuityEntities.js b/dapp/src/sagas/commuityEntities.js index c5920312..00dc39a0 100644 --- a/dapp/src/sagas/commuityEntities.js +++ b/dapp/src/sagas/commuityEntities.js @@ -80,44 +80,42 @@ function * removeAdminRole ({ account }) { yield call(transactionFlow, { transactionPromise, action, sendReceipt: true }) } -function * addUser ({ communityAddress, data, isClosed }) { - const accountAddress = yield select(getAccountAddress) - const CommunityContract = getContract({ abiName: 'Community', - address: communityAddress - }) - - let userRoles = isClosed ? roles.USER_ROLE : combineRoles(roles.USER_ROLE, roles.APPROVED_ROLE) - - const method = CommunityContract.methods.addEntity(data.account, userRoles) - const transactionPromise = method.send({ - from: accountAddress - }) - - const action = actions.ADD_ENTITY - yield call(transactionFlow, { transactionPromise, action, sendReceipt: true }) - yield call(createEntitiesMetadata, { communityAddress, accountId: data.account, metadata: data }) +function * deriveEntityData (data, isClosed) { + if (data.type === 'user') { + return { entityRoles: isClosed ? roles.USER_ROLE : combineRoles(roles.USER_ROLE, roles.APPROVED_ROLE) } + } else if (data.type === 'business') { + return { entityRoles: roles.BUSINESS_ROLE } + } } -function * addBusiness ({ communityAddress, data }) { +function * addEntity ({ communityAddress, data, isClosed }) { + const { entityRoles } = deriveEntityData(data, isClosed) + const accountAddress = yield select(getAccountAddress) const CommunityContract = getContract({ abiName: 'Community', address: communityAddress }) - const method = CommunityContract.methods.addEntity(data.account, roles.BUSINESS_ROLE) + const method = CommunityContract.methods.addEntity(data.account, entityRoles) const transactionPromise = method.send({ from: accountAddress }) const action = actions.ADD_ENTITY yield call(transactionFlow, { transactionPromise, action, sendReceipt: true }) - yield call(createEntitiesMetadata, { communityAddress, accountId: data.account, metadata: data }) + yield call(createEntitiesMetadata, { communityAddress, accountAddress: data.account, metadata: data }) } -function * addEntity ({ communityAddress, data, isClosed }) { - if (data.type === 'user') { - yield call(addUser, { communityAddress, data, isClosed }) - } else if (data.type === 'business') { - yield call(addBusiness, { communityAddress, data }) - } +function * joinCommunity ({ communityAddress, data }) { + // const accountAddress = yield select(getAccountAddress) + // const CommunityContract = getContract({ abiName: 'Community', + // address: communityAddress + // }) + // const method = CommunityContract.methods.join() + // const transactionPromise = method.send({ + // from: accountAddress + // }) + // const action = actions.ADD_ENTITY + // yield call(transactionFlow, { transactionPromise, action, sendReceipt: true }) + yield call(createEntitiesMetadata, { communityAddress, accountAddress: data.account, metadata: data }) } function * removeEntity ({ communityAddress, account }) { @@ -166,6 +164,7 @@ export default function * commuityEntitiesSaga () { tryTakeEvery(actions.ADD_ADMIN_ROLE, addAdminRole, 1), tryTakeEvery(actions.REMOVE_ADMIN_ROLE, removeAdminRole, 1), tryTakeEvery(actions.CONFIRM_USER, confirmUser, 1), + tryTakeEvery(actions.JOIN_COMMUNITY, joinCommunity, 1), takeEvery(action => /^(CREATE_METADATA|REMOVE_ENTITY|ADD_ADMIN_ROLE|REMOVE_ADMIN_ROLE|CONFIRM_USER).*SUCCESS/.test(action.type), watchEntityChanges) ]) } diff --git a/dapp/src/sagas/metadata.js b/dapp/src/sagas/metadata.js index 70b65187..bc06899d 100644 --- a/dapp/src/sagas/metadata.js +++ b/dapp/src/sagas/metadata.js @@ -1,6 +1,8 @@ import { all, put, takeEvery } from 'redux-saga/effects' import { createEntityPut, tryTakeEvery, apiCall } from './utils' +import { get3box } from 'services/web3' +import { separateData } from 'utils/3box' import * as entitiesApi from 'services/api/entities' import * as metadataApi from 'services/api/metadata' import * as actions from 'actions/metadata' @@ -38,15 +40,29 @@ export function * createMetadata ({ metadata }) { return { data, hash } } -export function * createEntitiesMetadata ({ communityAddress, accountId, metadata }) { - const { data, hash } = yield apiCall(entitiesApi.createEntitiesMetadata, { communityAddress, accountId, metadata }) +export function * createEntitiesMetadata ({ communityAddress, accountAddress, metadata }) { + const box = yield get3box({ accountAddress }) + console.log({ box }) + + const { publicData, privateData } = separateData(metadata) + + let fields = Object.keys(publicData) + let values = Object.values(publicData) + debugger + let response = yield box.public.setMultiple(fields, values) + debugger + + fields = Object.keys(privateData) + values = Object.values(privateData) + response = yield box.private.setMultiple(fields, values) + + // debugger + // const { data, hash } = yield apiCall(entitiesApi.createEntitiesMetadata, { communityAddress, accountId, metadata }) yield put({ type: actions.CREATE_METADATA.SUCCESS, - response: { - data - } + response: response }) - return { data, hash } + // return { data, hash } } function * watchTokensFetched ({ response }) { diff --git a/dapp/src/services/api/entities.js b/dapp/src/services/api/entities.js index 67fed548..6c01fa9d 100644 --- a/dapp/src/services/api/entities.js +++ b/dapp/src/services/api/entities.js @@ -7,8 +7,8 @@ export const fetchCommunityEntities = (apiRoot, { communityAddress, entityType } return request.get(path).then(response => response.body) } -export const createEntitiesMetadata = (apiRoot, { communityAddress, accountId, metadata }) => - request.put(`${apiRoot}/entities/${communityAddress}/${accountId}`) +export const createEntitiesMetadata = (apiRoot, { communityAddress, accountAddress, metadata }) => + request.put(`${apiRoot}/entities/${communityAddress}/${accountAddress}`) .send({ metadata }) .then(response => response.body) diff --git a/dapp/src/utils/3box.js b/dapp/src/utils/3box.js new file mode 100644 index 00000000..b81bf714 --- /dev/null +++ b/dapp/src/utils/3box.js @@ -0,0 +1,29 @@ + +export const addUser = (box, data) => { + +} + +export const publicFields = [ + 'firstName', + 'lastName', + 'country', + 'city', + 'account' +] + +export const privateFields = [ + 'email', + 'mainPhoneNumber', + 'secondPhoneNumber', + 'address' +] + +export const getPublicData = (data) => { + return publicFields.reduce((fields, field) => ({ ...fields, [field]: data[field] }), {}) +} + +export const getPrivateData = (data) => { + return privateFields.reduce((fields, field) => ({ ...fields, [field]: data[field] }), {}) +} + +export const separateData = (data) => ({ publicData: getPublicData(data), privateData: getPrivateData(data) }) From 247147a6c8a5f0c00c3c0bf6b2309451231995fd Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 19 Jun 2019 16:30:19 +0300 Subject: [PATCH 03/51] joining user --- dapp/src/actions/metadata.js | 1 + .../components/AddUserForm/index.jsx | 5 +++- .../dashboard/modals/AddUserModal/index.jsx | 4 ++-- .../dashboard/pages/Users/index.jsx | 3 ++- dapp/src/sagas/metadata.js | 21 +++++++--------- server/src/models/Profile.js | 24 +++++++++++++++++++ server/src/models/index.js | 1 + 7 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 server/src/models/Profile.js diff --git a/dapp/src/actions/metadata.js b/dapp/src/actions/metadata.js index ef11cd0e..6d2e7973 100644 --- a/dapp/src/actions/metadata.js +++ b/dapp/src/actions/metadata.js @@ -4,6 +4,7 @@ export const entityName = 'metadata' export const FETCH_METADATA = createRequestTypes('FETCH_METADATA') export const CREATE_METADATA = createRequestTypes('CREATE_METADATA') +export const CREATE_ENTITY_METADATA = createRequestTypes('CREATE_ENTITY_METADATA') export const fetchMetadata = (tokenURI) => action(FETCH_METADATA.REQUEST, { tokenURI }) export const createMetadata = (metadata) => action(CREATE_METADATA.REQUEST, { metadata }) diff --git a/dapp/src/components/dashboard/components/AddUserForm/index.jsx b/dapp/src/components/dashboard/components/AddUserForm/index.jsx index 58ebb64e..52f75c85 100644 --- a/dapp/src/components/dashboard/components/AddUserForm/index.jsx +++ b/dapp/src/components/dashboard/components/AddUserForm/index.jsx @@ -1,6 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import omit from 'lodash/omit' +import get from 'lodash/get' import { Formik, Field, ErrorMessage } from 'formik' import userEntity from 'utils/validation/shapes/userEntity' import TransactionButton from 'components/common/TransactionButton' @@ -11,6 +12,8 @@ class AddUserForm extends Component { constructor (props) { super(props) + const { entity } = props + this.initialValues = { firstName: '', lastName: '', @@ -20,7 +23,7 @@ class AddUserForm extends Component { country: '', city: '', address: '', - account: '' + account: get(entity, 'account', '') } this.validationSchema = userEntity diff --git a/dapp/src/components/dashboard/modals/AddUserModal/index.jsx b/dapp/src/components/dashboard/modals/AddUserModal/index.jsx index 35074754..f93657b7 100644 --- a/dapp/src/components/dashboard/modals/AddUserModal/index.jsx +++ b/dapp/src/components/dashboard/modals/AddUserModal/index.jsx @@ -2,7 +2,7 @@ import React from 'react' import Modal from 'components/common/Modal' import AddUserForm from '../../components/AddUserForm' -export default ({ hideModal, submitEntity }) => { +export default ({ hideModal, submitEntity, entity }) => { const handleSubmitUser = (...args) => { submitEntity(...args) hideModal() @@ -14,7 +14,7 @@ export default ({ hideModal, submitEntity }) => {
- +
) diff --git a/dapp/src/components/dashboard/pages/Users/index.jsx b/dapp/src/components/dashboard/pages/Users/index.jsx index 628b9705..a36291e3 100644 --- a/dapp/src/components/dashboard/pages/Users/index.jsx +++ b/dapp/src/components/dashboard/pages/Users/index.jsx @@ -88,8 +88,9 @@ class Users extends Component { loadAddUserModal = (isJoin) => { const submitEntity = isJoin ? this.props.joinCommunity : this.props.addEntity - const { loadModal } = this.props + const { loadModal, accountAddress } = this.props loadModal(ADD_USER_MODAL, { + entity: isJoin ? { account: accountAddress } : undefined, submitEntity: (data) => submitEntity(this.props.community.communityAddress, { ...data, type: 'user' }, this.props.isClosed) }) } diff --git a/dapp/src/sagas/metadata.js b/dapp/src/sagas/metadata.js index bc06899d..754889d2 100644 --- a/dapp/src/sagas/metadata.js +++ b/dapp/src/sagas/metadata.js @@ -41,26 +41,23 @@ export function * createMetadata ({ metadata }) { } export function * createEntitiesMetadata ({ communityAddress, accountAddress, metadata }) { + debugger const box = yield get3box({ accountAddress }) console.log({ box }) const { publicData, privateData } = separateData(metadata) + const publicFields = Object.keys(publicData) + const publicValues = Object.values(publicData) + yield box.public.setMultiple(publicFields, publicValues) - let fields = Object.keys(publicData) - let values = Object.values(publicData) - debugger - let response = yield box.public.setMultiple(fields, values) - debugger - - fields = Object.keys(privateData) - values = Object.values(privateData) - response = yield box.private.setMultiple(fields, values) + const privateFields = Object.keys(privateData) + const privateValues = Object.values(privateData) + yield box.private.setMultiple(privateFields, privateValues) - // debugger + debugger // const { data, hash } = yield apiCall(entitiesApi.createEntitiesMetadata, { communityAddress, accountId, metadata }) yield put({ - type: actions.CREATE_METADATA.SUCCESS, - response: response + type: actions.CREATE_METADATA.SUCCESS }) // return { data, hash } } diff --git a/server/src/models/Profile.js b/server/src/models/Profile.js new file mode 100644 index 00000000..89bbc672 --- /dev/null +++ b/server/src/models/Profile.js @@ -0,0 +1,24 @@ +module.exports = (mongoose) => { + mongoose = mongoose || require('mongoose') + const Schema = mongoose.Schema + const ProfileSchema = new Schema({ + account: { type: String, required: [true, "can't be blank"] }, + publicData: { type: Object, required: [true, "can't be blank"] } + }, { timestamps: true }) + + ProfileSchema.index({ account: 1 }, { unique: true }) + + ProfileSchema.set('toJSON', { + versionKey: false + }) + + const Profile = mongoose.model('Profile', ProfileSchema) + + function profile () {} + + profile.getModel = () => { + return Profile + } + + return profile +} diff --git a/server/src/models/index.js b/server/src/models/index.js index 6feb28f5..258f3fce 100644 --- a/server/src/models/index.js +++ b/server/src/models/index.js @@ -10,5 +10,6 @@ module.exports = (mongoose) => { mongoose.community = mongoose.community || require('./Community')(mongoose) mongoose.communityProgress = mongoose.communityProgress || require('./CommunityProgress')(mongoose) mongoose.entity = mongoose.entity || require('./Entity')(mongoose) + mongoose.profile = mongoose.profile || require('./Profile')(mongoose) return mongoose } From cc92ff50de31d1bdf5ecd5c7a70a03cddd382af8 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Thu, 20 Jun 2019 11:02:50 +0300 Subject: [PATCH 04/51] fixing backend --- dapp/src/sagas/commuityEntities.js | 20 ++++++++++---------- dapp/src/sagas/metadata.js | 11 ++++------- dapp/src/services/api/profiles.js | 6 ++++++ server/src/models/Entity.js | 3 ++- server/src/routes/api/entities.js | 12 ++++++------ server/src/routes/api/index.js | 1 + server/src/routes/api/profiles.js | 21 +++++++++++++++++++++ 7 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 dapp/src/services/api/profiles.js create mode 100644 server/src/routes/api/profiles.js diff --git a/dapp/src/sagas/commuityEntities.js b/dapp/src/sagas/commuityEntities.js index 00dc39a0..40ffd668 100644 --- a/dapp/src/sagas/commuityEntities.js +++ b/dapp/src/sagas/commuityEntities.js @@ -105,16 +105,16 @@ function * addEntity ({ communityAddress, data, isClosed }) { } function * joinCommunity ({ communityAddress, data }) { - // const accountAddress = yield select(getAccountAddress) - // const CommunityContract = getContract({ abiName: 'Community', - // address: communityAddress - // }) - // const method = CommunityContract.methods.join() - // const transactionPromise = method.send({ - // from: accountAddress - // }) - // const action = actions.ADD_ENTITY - // yield call(transactionFlow, { transactionPromise, action, sendReceipt: true }) + const accountAddress = yield select(getAccountAddress) + const CommunityContract = getContract({ abiName: 'Community', + address: communityAddress + }) + const method = CommunityContract.methods.join() + const transactionPromise = method.send({ + from: accountAddress + }) + const action = actions.ADD_ENTITY + yield call(transactionFlow, { transactionPromise, action, sendReceipt: true }) yield call(createEntitiesMetadata, { communityAddress, accountAddress: data.account, metadata: data }) } diff --git a/dapp/src/sagas/metadata.js b/dapp/src/sagas/metadata.js index 754889d2..69514fa6 100644 --- a/dapp/src/sagas/metadata.js +++ b/dapp/src/sagas/metadata.js @@ -3,7 +3,7 @@ import { all, put, takeEvery } from 'redux-saga/effects' import { createEntityPut, tryTakeEvery, apiCall } from './utils' import { get3box } from 'services/web3' import { separateData } from 'utils/3box' -import * as entitiesApi from 'services/api/entities' +import { createProfile } from 'services/api/profiles' import * as metadataApi from 'services/api/metadata' import * as actions from 'actions/metadata' import { FETCH_TOKEN } from 'actions/token' @@ -40,10 +40,8 @@ export function * createMetadata ({ metadata }) { return { data, hash } } -export function * createEntitiesMetadata ({ communityAddress, accountAddress, metadata }) { - debugger +export function * createEntitiesMetadata ({ accountAddress, metadata }) { const box = yield get3box({ accountAddress }) - console.log({ box }) const { publicData, privateData } = separateData(metadata) const publicFields = Object.keys(publicData) @@ -53,11 +51,10 @@ export function * createEntitiesMetadata ({ communityAddress, accountAddress, me const privateFields = Object.keys(privateData) const privateValues = Object.values(privateData) yield box.private.setMultiple(privateFields, privateValues) + yield apiCall(createProfile, { accountAddress, publicData }) - debugger - // const { data, hash } = yield apiCall(entitiesApi.createEntitiesMetadata, { communityAddress, accountId, metadata }) yield put({ - type: actions.CREATE_METADATA.SUCCESS + type: actions.CREATE_ENTITY_METADATA.SUCCESS }) // return { data, hash } } diff --git a/dapp/src/services/api/profiles.js b/dapp/src/services/api/profiles.js new file mode 100644 index 00000000..2d15fad0 --- /dev/null +++ b/dapp/src/services/api/profiles.js @@ -0,0 +1,6 @@ +import request from 'superagent' + +export const createProfile = (apiRoot, { accountAddress, publicData }) => + request.put(`${apiRoot}/profiles/${accountAddress}`) + .send({ publicData }) + .then(response => response.body) diff --git a/server/src/models/Entity.js b/server/src/models/Entity.js index 861a90f0..676afc51 100644 --- a/server/src/models/Entity.js +++ b/server/src/models/Entity.js @@ -9,7 +9,8 @@ module.exports = (mongoose) => { roles: { type: String, required: [true, "can't be blank"] }, type: { type: String, required: [true, "can't be blank"] }, isAdmin: { type: Boolean }, - isApproved: { type: Boolean } + isApproved: { type: Boolean }, + profile: { type: Schema.Types.ObjectId, ref: 'Profile' } }, { timestamps: true }) EntitySchema.index({ communityAddress: 1, account: 1 }, { unique: true }) diff --git a/server/src/routes/api/entities.js b/server/src/routes/api/entities.js index 6d84fbc0..ffc82229 100644 --- a/server/src/routes/api/entities.js +++ b/server/src/routes/api/entities.js @@ -109,17 +109,17 @@ const getQueryFilter = ({ query: { type }, params: { communityAddress } }) => */ router.get('/:communityAddress', async (req, res, next) => { const queryFilter = getQueryFilter(req) - const { withMetadata } = req.query + // const { withMetadata } = req.query let [ results, itemCount ] = await Promise.all([ - Entity.find(queryFilter).sort({ name: 1 }).limit(req.query.limit).skip(req.skip), + Entity.find(queryFilter).sort({ name: 1 }).limit(req.query.limit).skip(req.skip).populate('profile'), Entity.countDocuments(queryFilter) ]) - if (withMetadata) { - const metadatas = await Promise.all(results.map(result => result.uri ? getMetadata(result.uri.split('://')[1]).catch(console.error) : null)) - results = results.map((result, index) => ({ ...result.toObject(), metadata: metadatas[index] && metadatas[index].data })) - } + // if (withMetadata) { + // const metadatas = await Promise.all(results.map(result => result.uri ? getMetadata(result.uri.split('://')[1]).catch(console.error) : null)) + // results = results.map((result, index) => ({ ...result.toObject(), metadata: metadatas[index] && metadatas[index].data })) + // } const pageCount = Math.ceil(itemCount / req.query.limit) diff --git a/server/src/routes/api/index.js b/server/src/routes/api/index.js index 2e218199..cf8a0e1f 100644 --- a/server/src/routes/api/index.js +++ b/server/src/routes/api/index.js @@ -13,6 +13,7 @@ router.use('/bridges', require('./bridges')) router.use('/communities', require('./communities')) router.use('/deployments', require('./deployments')) router.use('/entities', require('./entities')) +router.use('/profiles', require('./profiles')) router.use(function (err, req, res, next) { if (err.name === 'ValidationError') { diff --git a/server/src/routes/api/profiles.js b/server/src/routes/api/profiles.js new file mode 100644 index 00000000..9e8cce2b --- /dev/null +++ b/server/src/routes/api/profiles.js @@ -0,0 +1,21 @@ +const router = require('express').Router() +const mongoose = require('mongoose') +const Profile = mongoose.model('Profile') +const Entity = mongoose.model('Entity') + +router.put('/:account', async (req, res) => { + const { account } = req.params + const { publicData } = req.body + + let profile + try { + profile = await new Profile({ account, publicData }).save() + await Entity.findOneAndUpdate({ account }, { profile: profile._id }) + } catch (error) { + profile = Profile.findOneAndUpdate({ account }, { publicData }, { new: true }) + } + + return res.json({ data: profile }) +}) + +module.exports = router From 57f20948134c636bffa58a45f50a32d0bcafd646 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Thu, 20 Jun 2019 11:03:34 +0300 Subject: [PATCH 05/51] fix lint --- server/src/routes/api/entities.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/routes/api/entities.js b/server/src/routes/api/entities.js index ffc82229..cbfb2428 100644 --- a/server/src/routes/api/entities.js +++ b/server/src/routes/api/entities.js @@ -3,7 +3,6 @@ const router = require('express').Router() const mongoose = require('mongoose') const Entity = mongoose.model('Entity') const metadataUtils = require('@utils/metadata') -const { getMetadata } = require('@utils/metadata') const Community = mongoose.model('Community') const Token = mongoose.model('Token') const { sortBy, keyBy } = require('lodash') From c3f2bda4cfcee2696197f984555d46a3a9d47cc7 Mon Sep 17 00:00:00 2001 From: Lior Date: Sun, 23 Jun 2019 18:03:00 +0300 Subject: [PATCH 06/51] first commit --- dapp/src/actions/communityEntities.js | 4 + .../components/BusinessForm/index.jsx | 14 +- .../modals/ImportExistingEntity/index.jsx | 148 ++++++++++++++++++ .../dashboard/pages/Businesses/index.jsx | 10 +- .../dashboard/pages/Users/index.jsx | 74 ++++++--- dapp/src/constants/uiConstants.js | 1 + dapp/src/containers/ModalContainer.jsx | 7 +- .../src/reducers/screens/communityEntities.js | 4 +- dapp/src/sagas/commuityEntities.js | 41 ++++- dapp/src/sagas/metadata.js | 4 +- .../scss/components/dashboard/Dashboard.scss | 8 +- .../components/dashboard/EntitiesManager.scss | 40 ++--- .../components/dashboard/ExistingEntity.scss | 82 ++++++++++ dapp/src/scss/main.scss | 1 + dapp/src/scss/variables.scss | 1 + dapp/src/services/api/images.js | 15 ++ dapp/src/utils/network.js | 2 +- server/src/events/handlers/community.js | 8 +- server/src/routes/api/profiles.js | 3 +- 19 files changed, 402 insertions(+), 65 deletions(-) create mode 100644 dapp/src/components/dashboard/modals/ImportExistingEntity/index.jsx create mode 100644 dapp/src/scss/components/dashboard/ExistingEntity.scss create mode 100644 dapp/src/services/api/images.js diff --git a/dapp/src/actions/communityEntities.js b/dapp/src/actions/communityEntities.js index 8f3280e0..0b29a3e7 100644 --- a/dapp/src/actions/communityEntities.js +++ b/dapp/src/actions/communityEntities.js @@ -18,6 +18,8 @@ export const CONFIRM_USER = createTransactionRequestTypes('CONFIRM_USER') export const FETCH_ENTITY = createRequestTypes('FETCH_ENTITY') export const JOIN_COMMUNITY = createRequestTypes('JOIN_COMMUNITY') +export const IMPORT_EXISTING_ENTITY = createRequestTypes('IMPORT_EXISTING_ENTITY') +export const UPLOAD_IMAGE = createRequestTypes('UPLOAD_IMAGE') export const fetchEntities = (communityAddress) => entitiesAction(FETCH_USERS_ENTITIES.REQUEST, { communityAddress }) export const fetchUsersEntities = (communityAddress, entityType = 'user') => entitiesAction(FETCH_USERS_ENTITIES.REQUEST, { communityAddress, entityType }) @@ -32,5 +34,7 @@ export const removeAdminRole = (account) => action(REMOVE_ADMIN_ROLE.REQUEST, { export const confirmUser = (account) => action(CONFIRM_USER.REQUEST, { account }) export const editEntity = (listAddress, hash, data) => action(EDIT_ENTITY.REQUEST, { listAddress, hash, data }) export const joinCommunity = (communityAddress, data) => action(JOIN_COMMUNITY.REQUEST, { communityAddress, data }) +export const importExistingEntity = (accountAddress, communityAddress, isClosed) => action(IMPORT_EXISTING_ENTITY.REQUEST, { accountAddress, communityAddress, isClosed }) +export const uploadImage = (image) => action(UPLOAD_IMAGE.REQUEST, { image }) export const toggleCommunityMode = (communityAddress, isClosed) => action(TOGGLE_COMMUNITY_MODE.REQUEST, { communityAddress, isClosed }) diff --git a/dapp/src/components/dashboard/components/BusinessForm/index.jsx b/dapp/src/components/dashboard/components/BusinessForm/index.jsx index 6d4b8bb3..23a4ff62 100644 --- a/dapp/src/components/dashboard/components/BusinessForm/index.jsx +++ b/dapp/src/components/dashboard/components/BusinessForm/index.jsx @@ -35,6 +35,14 @@ class BusinessForm extends Component { this.validationSchema = entityShape } + setUploadCoverPicture = (node) => { + this.uploadCoverPicture = node + } + + setUploadLogoPicture = (node) => { + this.uploadLogoPicture = node + } + onSubmit = (values) => { const { submitEntity @@ -62,8 +70,9 @@ class BusinessForm extends Component { Logo 

-