Skip to content

Commit

Permalink
Merge pull request #333 from tasitlabs/feature/myassets-refresh-fix
Browse files Browse the repository at this point in the history
MyLand refresh/navigation fix
  • Loading branch information
pcowgill authored Apr 24, 2019
2 parents 40ec816 + 22799c5 commit 0665819
Show file tree
Hide file tree
Showing 24 changed files with 521 additions and 197 deletions.
2 changes: 1 addition & 1 deletion decentraland/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = {
"plugin:jest/recommended",
],
rules: {
"no-console": ["error", { allow: ["warn", "error"] }],
"no-console": ["error", { allow: ["warn", "error", "info"] }],
"react-native/no-raw-text": ["error", { skip: ["LargeText"] }],
"react/prop-types": ["error", { ignore: ["navigation"] }],
"prettier/prettier": "error",
Expand Down
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
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're 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,
};
26 changes: 24 additions & 2 deletions decentraland/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ export const showError = msg => showToast(`ERROR: ${msg}`);
export const showWarn = msg => showToast(`WARN: ${msg}`);
export const showInfo = msg => showToast(`${msg}`);

export const logInfo = msg => console.info(msg);
export const logWarn = msg => console.warn(msg);
export const logError = msg => console.error(msg);

export const checkBlockchain = async () => {
loadConfig();
const provider = ProviderFactory.getProvider();
Expand All @@ -160,8 +164,14 @@ export const formatNumber = number => {
return formattedNumber;
};

export const removeFromList = (list, toRemove) =>
list.filter(e => e !== toRemove);
export const toListIfNot = itemOrList =>
Array.isArray(itemOrList) ? itemOrList : [itemOrList];

export const removeFromList = (list, toRemove) => {
const elementsToRemove = toListIfNot(toRemove);
const idsToRemove = elementsToRemove.map(e => e.id);
return list.filter(e => !idsToRemove.includes(e.id));
};

export const listsAreEqual = (first, second) => {
if (first.length !== second.length) return false;
Expand All @@ -171,6 +181,13 @@ export const listsAreEqual = (first, second) => {
);
};

// Update item from any list of objects having id as key field
export const updateListItem = (list, toUpdateId, entriesToUpdate) => {
return list.map(item => {
return item.id === toUpdateId ? { ...item, ...entriesToUpdate } : item;
});
};

const loadConfig = () => {
const tasitSdkConfig = require("../config/current.js");
ConfigLoader.setConfig(tasitSdkConfig);
Expand Down Expand Up @@ -244,6 +261,9 @@ export default {
showError,
showWarn,
showInfo,
logInfo,
logWarn,
logError,
fundAccountWithEthers,
fundAccountWithMana,
getContracts,
Expand All @@ -255,4 +275,6 @@ export default {
getNetworkName,
buildBlockchainUrlFromActionId,
restoreCreationStateOfAccountFromBlockchain,
updateListItem,
toListIfNot,
};
Loading

0 comments on commit 0665819

Please sign in to comment.