Skip to content

Commit

Permalink
userActions reducer
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelomorgado committed Apr 23, 2019
1 parent 78e319c commit b196afa
Show file tree
Hide file tree
Showing 23 changed files with 284 additions and 129 deletions.
18 changes: 18 additions & 0 deletions decentraland/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
setMyAssetsList,
setAccountCreationStatus,
setAccountCreationActions,
addUserAction,
} from "./redux/actions";
import applyMiddleware from "./redux/middlewares";
import { Action } from "tasit-sdk";
Expand All @@ -28,9 +29,11 @@ import {
retrieveAccountCreationActions,
storeIsFirstUse,
retrieveIsFirstUse,
retrieveUserActions,
} from "@helpers/storage";
import { Ionicons } from "@expo/vector-icons";
import { Root } from "native-base";
import { SUCCESSFUL } from "@constants/UserActionStatus";

const store = createStore(decentralandApp, applyMiddleware);

Expand Down Expand Up @@ -99,6 +102,21 @@ Is the config file correct?`;

async _loadMyAssets() {
const myAssets = await retrieveMyAssets();
const userActions = await retrieveUserActions();

// Handling with actions stored before
// the introduction of userAction state (<= 0.0.17)
myAssets.forEach(asset => {
const { id: assetId, actionId } = asset;
let userAction = userActions.find(action => action.assetId === assetId);

if (!userAction && !!actionId) {
userAction = { actionId, assetId, status: SUCCESSFUL };
userActions.push(userAction);
}
});

if (userActions) store.dispatch(addUserAction(userActions));
if (myAssets) store.dispatch(setMyAssetsList(myAssets));
}

Expand Down
15 changes: 8 additions & 7 deletions decentraland/components/presentational/MyAsset.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import PropTypes from "prop-types";
import { responsiveWidth } from "react-native-responsive-dimensions";
import Estate from "./Estate";
import Parcel from "./Parcel";
import AssetTypes from "@constants/AssetTypes";
import { ESTATE, PARCEL } from "@constants/AssetTypes";
import LinkToBlockchain from "./LinkToBlockchain";
import AssetName from "./AssetName";

const { ESTATE, PARCEL } = AssetTypes;

export function MyAsset({ asset }) {
export function MyAsset({ asset, userAction }) {
const { type } = asset;

return (
Expand All @@ -23,17 +21,19 @@ export function MyAsset({ asset }) {
return <Parcel parcel={asset} />;
}
})()}
<MyAssetInfo asset={asset} />
<MyAssetInfo asset={asset} userAction={userAction} />
</View>
);
}

MyAsset.propTypes = {
asset: PropTypes.object.isRequired,
userAction: PropTypes.object.isRequired,
};

export function MyAssetInfo({ asset }) {
const { actionId, name } = asset;
export function MyAssetInfo({ asset, userAction }) {
const { name } = asset;
const { actionId } = userAction;

return (
<View style={styles.myAssetInfoContainer}>
Expand All @@ -49,6 +49,7 @@ export function MyAssetInfo({ asset }) {

MyAssetInfo.propTypes = {
asset: PropTypes.object.isRequired,
userAction: PropTypes.object.isRequired,
};

const styles = StyleSheet.create({
Expand Down
16 changes: 13 additions & 3 deletions decentraland/components/presentational/MyAsset.test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import React from "react";
import { shallow } from "enzyme";
import { MyAsset, MyAssetInfo } from "./MyAsset";
import { parcel } from "@helpers/testHelpers";
import { parcel, parcelUserAction } from "@helpers/testHelpers";

describe("MyAsset", () => {
it("renders the component", async () => {
expect(shallow(<MyAsset asset={parcel} />)).toMatchSnapshot();
const asset = parcel;
const userAction = parcelUserAction;

expect(
shallow(<MyAsset asset={asset} userAction={userAction} />)
).toMatchSnapshot();
});

describe("MyAssetInfo", () => {
it("renders the component", async () => {
expect(shallow(<MyAssetInfo asset={parcel} />)).toMatchSnapshot();
const asset = parcel;
const userAction = parcelUserAction;

expect(
shallow(<MyAssetInfo asset={asset} userAction={userAction} />)
).toMatchSnapshot();
});
});
});
18 changes: 13 additions & 5 deletions decentraland/components/presentational/MyAssetsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,35 @@ import LargeText from "@presentational/LargeText";
// https://medium.com/groww-engineering/stateless-component-vs-pure-component-d2af88a1200b
export default class MyAssetsList extends React.PureComponent {
render() {
const { myAssetsList, renderItem } = this.props;
const { length: listAmount } = myAssetsList;
const { myAssets, userActions, renderItem } = this.props;
const { length: listAmount } = myAssets;

const dataList = myAssets.map(asset => {
let userAction = userActions.find(action => action.assetId === asset.id);
return { asset, userAction };
});

const withoutAssets = listAmount === 0;

return withoutAssets ? (
<View style={styles.emptyContainer}>
<LargeText>{`You haven't bought any land yet.`}</LargeText>
</View>
) : (
<FlatList
data={myAssetsList}
data={dataList}
style={styles.container}
renderItem={renderItem}
keyExtractor={item => item.id}
keyExtractor={item => item.asset.id}
/>
);
}
}

MyAssetsList.propTypes = {
renderItem: PropTypes.func.isRequired,
myAssetsList: PropTypes.array.isRequired,
myAssets: PropTypes.array.isRequired,
userActions: PropTypes.array.isRequired,
};

const styles = StyleSheet.create({
Expand Down
13 changes: 8 additions & 5 deletions decentraland/components/presentational/MyAssetsList.test.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
import React from "react";
import { shallow } from "enzyme";
import MyAssetsList from "./MyAssetsList";
import { estate } from "@helpers/testHelpers";
import { estate, userActions } from "@helpers/testHelpers";

describe("MyAssetsList", () => {
describe("renders the component", () => {
const myAssetRenderer = () => {};

it("without assets", async () => {
const myAssetsList = [];
const myAssets = [];

expect(
shallow(
<MyAssetsList
myAssetsList={myAssetsList}
myAssets={myAssets}
renderItem={myAssetRenderer}
userActions={userActions}
/>
)
).toMatchSnapshot();
});

it("with assets", async () => {
const myAssetsList = [estate];
const myAssets = [estate];
expect(
shallow(
<MyAssetsList
myAssetsList={myAssetsList}
myAssets={myAssets}
renderItem={myAssetRenderer}
userActions={userActions}
/>
)
).toMatchSnapshot();
Expand Down
5 changes: 3 additions & 2 deletions decentraland/components/presentational/MyAssetsListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import MyAsset from "./MyAsset";
// https://medium.com/groww-engineering/stateless-component-vs-pure-component-d2af88a1200b
export default class MyAssetsListItem extends React.PureComponent {
render() {
const { asset } = this.props;
const { asset, userAction } = this.props;
return (
<TouchableHighlight>
<View style={styles.row}>
<MyAsset asset={asset} />
<MyAsset asset={asset} userAction={userAction} />
</View>
</TouchableHighlight>
);
Expand All @@ -27,6 +27,7 @@ export default class MyAssetsListItem extends React.PureComponent {

MyAssetsListItem.propTypes = {
asset: PropTypes.object.isRequired,
userAction: PropTypes.object.isRequired,
};

const styles = StyleSheet.create({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React from "react";
import { shallow } from "enzyme";
import MyAssetsListItem from "./MyAssetsListItem";
import { parcel } from "@helpers/testHelpers";
import { parcel, parcelUserAction } from "@helpers/testHelpers";

describe("MyAssetsListItem", () => {
it("renders the component", async () => {
expect(shallow(<MyAssetsListItem asset={parcel} />)).toMatchSnapshot();
const asset = parcel;
const userAction = parcelUserAction;
expect(
shallow(<MyAssetsListItem asset={asset} userAction={userAction} />)
).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ exports[`MyAsset MyAssetInfo renders the component 1`] = `
}
}
>
<LinkToBlockchain />
<LinkToBlockchain
actionId="0x1234567890123456789012345678901234567890"
/>
</Component>
</Component>
`;
Expand Down Expand Up @@ -61,6 +63,13 @@ exports[`MyAsset renders the component 1`] = `
"type": "PARCEL",
}
}
userAction={
Object {
"actionId": "0x1234567890123456789012345678901234567890",
"assetId": "0123456789",
"status": "SUCCESSFUL",
}
}
/>
</Component>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ exports[`MyAssetsList renders the component with assets 1`] = `
data={
Array [
Object {
"id": "123",
"img": "https://api.decentraland.org/v1/estates/1/map.png",
"name": "Sample Estate",
"type": "ESTATE",
"asset": Object {
"id": "123",
"img": "https://api.decentraland.org/v1/estates/1/map.png",
"name": "Sample Estate",
"type": "ESTATE",
},
"userAction": Object {
"actionId": "0x987654321098765432109876543210987654321",
"assetId": "123",
"status": "SUCCESSFUL",
},
},
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ exports[`MyAssetsListItem renders the component 1`] = `
"type": "PARCEL",
}
}
userAction={
Object {
"actionId": "0x1234567890123456789012345678901234567890",
"assetId": "0123456789",
"status": "SUCCESSFUL",
}
}
/>
</Component>
</TouchableHighlight>
Expand Down
4 changes: 2 additions & 2 deletions decentraland/constants/AssetTypes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const ESTATE = "ESTATE";
const PARCEL = "PARCEL";
export const ESTATE = "ESTATE";
export const PARCEL = "PARCEL";

export default {
ESTATE,
Expand Down
7 changes: 0 additions & 7 deletions decentraland/constants/MyAssetStatus.js

This file was deleted.

17 changes: 17 additions & 0 deletions decentraland/constants/UserActionStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// To be used for meta-tx
export const BROADCASTED = "BROADCASTED";

export const PENDING = "PENDING";
export const FAILED = "FAILED";

// Note: We are using only 'SUCCESSFUL' for now
// When we'll tracking confirmations that will be used for >= 7
// and 'PROBABLY_SUCCESSFUL' to < 7 confirmations.
export const PROBABLY_SUCCESSFUL = "PROBABLY_SUCCESSFUL";
export const SUCCESSFUL = "SUCCESSFUL";

export default {
PENDING,
FAILED,
SUCCESSFUL,
};
15 changes: 15 additions & 0 deletions decentraland/helpers/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ const MY_ASSETS_LIST = "MY_ASSETS_LIST";
const EPHEMERAL_ACCOUNT_CREATION_STATUS = "EPHEMERAL_ACCOUNT_CREATION_STATUS";
const EPHEMERAL_ACCOUNT_CREATION_ACTIONS = "EPHEMERAL_ACCOUNT_CREATION_ACTIONS";
const IS_FIRST_APP_USE = "IS_FIRST_APP_USE";
const USER_ACTIONS = "USER_ACTIONS";

export const storeUserActions = async userActions => {
const strUserActions = _toString(userActions);
await _storeData(USER_ACTIONS, strUserActions, false);
};

export const retrieveUserActions = async () => {
const strUserActions = await _retrieveData(USER_ACTIONS);
const userActions = _fromString(strUserActions);
if (userActions === null) return [];
return userActions;
};

export const storeIsFirstUse = async isFirstUse => {
const strIsFirstUse = _toString(isFirstUse);
Expand Down Expand Up @@ -127,4 +140,6 @@ export default {
retrieveAccountCreationActions,
storeIsFirstUse,
retrieveIsFirstUse,
retrieveUserActions,
storeUserActions,
};
21 changes: 19 additions & 2 deletions decentraland/helpers/testHelpers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import AssetTypes from "@constants/AssetTypes";
import { ESTATE, PARCEL } from "@constants/AssetTypes";
import { DONE, PENDING, MISSING } from "@constants/ActionStatus";
const { ESTATE, PARCEL } = AssetTypes;
import { SUCCESSFUL } from "@constants/UserActionStatus";

export const parcel = {
type: PARCEL,
Expand Down Expand Up @@ -56,11 +56,28 @@ export const accountCreationSteps = [
},
];

export const parcelUserAction = {
actionId: "0x1234567890123456789012345678901234567890",
assetId: "0123456789",
status: SUCCESSFUL,
};

export const estateUserAction = {
actionId: "0x987654321098765432109876543210987654321",
assetId: "123",
status: SUCCESSFUL,
};

export const userActions = [parcelUserAction, estateUserAction];

export default {
estateForSale,
parcelForSale,
parcel,
estate,
anAction,
estateWithoutName,
parcelUserAction,
estateUserAction,
userActions,
};
Loading

0 comments on commit b196afa

Please sign in to comment.