Items cleanup

This commit is contained in:
Belen Curcio
2017-01-25 05:15:04 -03:00
parent 622afcc80f
commit e3b183c565
9 changed files with 12 additions and 384 deletions
-1
View File
@@ -181,7 +181,6 @@ class Embed extends Component {
}
const mapStateToProps = state => ({
items: state.items.toJS(),
notification: state.notification.toJS(),
auth: state.auth.toJS(),
userData: state.user.toJS()
@@ -1,25 +1,3 @@
fragment commentView on Comment {
id
body
created_at
user {
id
name: displayName
settings {
bio
}
}
actions {
type: action_type
count
current: current_user {
id
created_at
}
}
}
query AssetQuery($asset_url: String!) {
asset(url: $asset_url) {
id
-3
View File
@@ -3,7 +3,6 @@ import translations from './../translations';
const lang = new I18n(translations);
import * as actions from '../constants/auth';
import coralApi, {base} from '../helpers/response';
import {addItem} from './items';
// Dialog Actions
export const showSignInDialog = (offset = 0) => ({type: actions.SHOW_SIGNIN_DIALOG, offset});
@@ -30,7 +29,6 @@ export const fetchSignIn = (formData) => (dispatch) => {
const isAdmin = !!user.roles.filter(i => i === 'ADMIN').length;
dispatch(signInSuccess(user, isAdmin));
dispatch(hideSignInDialog());
dispatch(addItem(user, 'users'));
})
.catch(() => dispatch(signInFailure(lang.t('error.emailPasswordError'))));
};
@@ -59,7 +57,6 @@ export const facebookCallback = (err, data) => dispatch => {
const user = JSON.parse(data);
dispatch(signInFacebookSuccess(user));
dispatch(hideSignInDialog());
dispatch(addItem(user, 'users'));
} catch (err) {
dispatch(signInFacebookFailure(err));
return;
-268
View File
@@ -1,268 +0,0 @@
import coralApi from '../helpers/response';
import {fromJS} from 'immutable';
import {UPDATE_CONFIG} from '../constants/config';
/**
* Action name constants
*/
export const ADD_ITEM = 'ADD_ITEM';
export const UPDATE_ITEM = 'UPDATE_ITEM';
export const APPEND_ITEM_ARRAY = 'APPEND_ITEM_ARRAY';
/**
* Action creators
*/
/*
* Adds an item to the local store without posting it to the server
* Useful for optimistic posting, etc.
*
* @params
* item - the item to be posted
*
*/
export const addItem = (item, item_type) => {
if (!item.id) {
console.warn('addItem called without an item id.');
}
return {
type: ADD_ITEM,
item,
item_type,
id: item.id
};
};
/*
* Updates an item in the local store without posting it to the server
* Useful for item-level toggles, etc.
*
* @params
* id - the id of the item to be posted
* property - the property to be updated
* value - the value that the property should be set to
* item_type - the type of the item being updated (users, comments, etc)
*
*/
export const updateItem = (id, property, value, item_type) => {
return {
type: UPDATE_ITEM,
id,
property,
value,
item_type
};
};
/*
* Appends data to an array in an item in the local store without posting it to the server
* Useful for adding a recently posted reply to a comment, etc.
*
* @params
* id - the id of the item to be posted
* property - the property to be updated (should be an array)
* value - the value that should be added to the array
* add_to_front - boolean that defines whether value is added at the beginning (unshift) or end (push)
* item_type - the type of the item being updated (users, comments, etc)
*
*/
export const appendItemArray = (id, property, value, add_to_front, item_type) => {
return {
type: APPEND_ITEM_ARRAY,
id,
property,
value,
add_to_front,
item_type
};
};
/*
* Get Items from Query
* Gets a set of items from a predefined query
*
* @params
* Query - a predefiend query for retreiving items
*
* @returns
* A promise resolving to a set of items
*
* @dispatches
* A set of items to the item store
*/
export function getStream (assetUrl) {
return (dispatch) => {
return coralApi(`/stream?asset_url=${encodeURIComponent(assetUrl)}`)
.then((json) => {
/* Add items to the store */
Object.keys(json).forEach(type => {
if (type === 'actions') {
json[type].forEach(action => {
action.id = `${action.action_type}_${action.item_id}`;
dispatch(addItem(action, 'actions'));
});
} else if (type === 'settings') {
dispatch({type: UPDATE_CONFIG, config: fromJS(json[type])});
} else {
json[type].forEach(item => {
dispatch(addItem(item, type));
});
}
});
const assetId = json.assets[0].id;
/* Sort comments by date*/
json.comments.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
const rels = json.comments.reduce((h, item) => {
/* Check for root and child comments. */
if (
item.asset_id === assetId &&
!item.parent_id) {
h.rootComments.push(item.id);
} else if (
item.asset_id === assetId
) {
let children = h.childComments[item.parent_id] || [];
h.childComments[item.parent_id] = children.concat(item.id);
}
return h;
}, {rootComments: [], childComments: {}});
dispatch(updateItem(assetId, 'comments', rels.rootComments, 'assets'));
Object.keys(rels.childComments).forEach(key => {
dispatch(updateItem(key, 'children', rels.childComments[key].reverse(), 'comments'));
});
/* Hydrate actions on comments */
json.actions.forEach(action => {
dispatch(updateItem(action.item_id, action.action_type, action.id, 'comments'));
});
return (json);
});
};
}
/*
* Get Items Array
* Gets a set of items from an array of item ids
*
* @params
* Query - a predefiend query for retreiving items
*
* @returns
* A promise resolving to a set of items
*
* @dispatches
* A set of items to the item store
*/
export function getItemsArray (ids) {
return (dispatch) => {
return coralApi(`/item/${ids}`)
.then((json) => {
for (let i = 0; i < json.items.length; i++) {
dispatch(addItem(json.items[i]));
}
return json.items;
});
};
}
/*
* PutItem
* Puts an item
*
* @params
* Item - the item to be put
*
* @returns
* A promise resolving to an item is
*
* @dispatches
* The newly put item to the item store
*/
export function postItem (item, type, id, mutate) {
console.log(
item,
type,
id,
mutate
);
mutate({
variables: {
asset_id: id,
body: item,
parent_id: null
}
}).then(({data}) => {
console.log('it workt');
console.log(data);
});
// return (dispatch) => {
// if (id) {
// item.id = id;
// }
// return coralApi(`/${type}`, {method: 'POST', body: item})
// .then((json) => {
// dispatch(addItem({...item, id:json.id}, type));
// return json;
// });
// };
}
/*
* PostAction
* Posts an action to an item
*
* @params
* id - the id of the item on which the action is taking place
* action - the action object.
* Must include an 'action_type' string.
* May optionally include a `metadata` object with arbitrary action data.
* user - the user performing the action
* host - the coral host
*
* @returns
* A promise resolving to null or an error
*
*/
export function postAction (item_id, item_type, action) {
return (dispatch) => {
return coralApi(`/${item_type}/${item_id}/actions`, {method: 'POST', body: action})
.then((json) => {
dispatch(updateItem(action.item_id, action.action_type, action.id, item_type));
return json;
});
};
}
/*
* DeleteAction
* Deletes an action to an item
*
* @params
* id - the id of the item on which the action is taking place
* action - the name of the action
* user - the user performing the action
* host - the coral host
*
* @returns
* A promise resolving to null or an error
*
*/
export function deleteAction (action_id) {
return () => {
return coralApi(`/actions/${action_id}`, {method: 'DELETE'});
};
}
+1 -24
View File
@@ -1,7 +1,6 @@
import * as actions from '../constants/user';
import * as assetActions from '../constants/assets';
import {addNotification} from '../actions/notification';
import {addItem} from '../actions/items';
import coralApi from '../helpers/response';
import I18n from 'coral-framework/modules/i18n/i18n';
@@ -30,27 +29,5 @@ export const saveBio = (user_id, formData) => dispatch => {
* @returns Promise
*/
export const fetchCommentsByUserId = userId => {
return (dispatch, getState) => {
dispatch({type: actions.COMMENTS_BY_USER_REQUEST});
return coralApi(`/comments?user_id=${userId}`)
.then(({comments, assets}) => {
const state = getState();
comments.forEach(comment => dispatch(addItem(comment, 'comments')));
assets.forEach(asset => {
const prevAsset = state.items.getIn(['assets', asset.id]);
if (prevAsset) {
// Include data such as hydrated comments from assets already in the system.
dispatch(addItem({...prevAsset.toJS(), ...asset}, 'assets'));
} else {
dispatch(addItem(asset, 'assets'));
}
});
dispatch({type: actions.COMMENTS_BY_USER_SUCCESS, comments: comments.map(comment => comment.id)});
dispatch({type: assetActions.MULTIPLE_ASSETS_SUCCESS, assets: assets.map(asset => asset.id)});
})
.catch(error => dispatch({type: actions.COMMENTS_BY_USER_FAILURE, error}));
};
// TODO
};
+7 -9
View File
@@ -1,19 +1,17 @@
import Notification from './modules/notification/Notification';
import store from './store';
import * as itemActions from './actions/items';
import pym from './PymConnection';
import I18n from './modules/i18n/i18n';
import * as notificationActions from './actions/notification';
import * as authActions from './actions/auth';
import * as assetActions from './actions/asset';
import pym from './PymConnection';
import * as notificationActions from './actions/notification';
import Notification from './modules/notification/Notification';
export {
Notification,
store,
itemActions,
pym,
I18n,
notificationActions,
store,
authActions,
assetActions,
pym
Notification,
notificationActions
};
-2
View File
@@ -1,13 +1,11 @@
import auth from './auth';
import user from './user';
import asset from './asset';
import items from './items';
import notification from './notification';
export default {
auth,
user,
asset,
items,
notification
};
-30
View File
@@ -1,30 +0,0 @@
/* Items Reducer */
import {fromJS} from 'immutable';
import * as actions from '../actions/items';
const initialState = fromJS({
comments: {},
users: {},
assets: {},
actions: {}
});
export default (state = initialState, action) => {
switch (action.type) {
case actions.ADD_ITEM:
return state.setIn([action.item_type, action.id], fromJS(action.item));
case actions.UPDATE_ITEM:
return state.setIn([action.item_type, action.id, action.property], fromJS(action.value));
case actions.APPEND_ITEM_ARRAY:
return state.updateIn([action.item_type, action.id, action.property], (prop) => {
if (action.add_to_front) {
return prop ? prop.unshift(fromJS(action.value)) : fromJS([action.value]);
} else {
return prop ? prop.push(fromJS(action.value)) : fromJS([action.value]);
}
});
default:
return state;
}
};
@@ -6,7 +6,7 @@ import {saveBio, fetchCommentsByUserId} from 'coral-framework/actions/user';
import {link} from 'coral-framework/PymConnection';
import BioContainer from './BioContainer';
import NotLoggedIn from '../components/NotLoggedIn';
import {TabBar, Tab, TabContent} from '../../coral-ui';
import {TabBar, Tab, TabContent} from 'coral-ui';
import CommentHistory from 'coral-plugin-history/CommentHistory';
import SettingsHeader from '../components/SettingsHeader';
import RestrictedContent from 'coral-framework/components/RestrictedContent';
@@ -26,9 +26,7 @@ class SettingsContainer extends Component {
}
componentWillMount () {
// Fetch commentHistory
this.props.fetchCommentsByUserId(this.props.userData.id);
// this.props.fetchCommentsByUserId(this.props.userData.id);
}
handleTabChange(tab) {
@@ -41,16 +39,6 @@ class SettingsContainer extends Component {
const {loggedIn, userData, showSignInDialog, items, user} = this.props;
const {activeTab} = this.state;
const commentsMostRecentFirst = user
.myComments.map(id => items.comments[id])
.sort(({created_at:a}, {created_at:b}) => {
// descending order, created_at
// js date strings can be sorted lexigraphically.
const aLessThanB = a < b ? 1 : 0;
return a > b ? -1 : aLessThanB;
});
return (
<RestrictedContent restricted={!loggedIn} restrictedComp={<NotLoggedIn showSignInDialog={showSignInDialog} />}>
<SettingsHeader {...this.props} />
@@ -59,14 +47,7 @@ class SettingsContainer extends Component {
<Tab>Profile Settings</Tab>
</TabBar>
<TabContent show={activeTab === 0}>
{
user.myComments.length && user.myAssets.length
? <CommentHistory
comments={commentsMostRecentFirst}
link={link}
assets={user.myAssets.map(id => items.assets[id])} />
: <p>{lang.t('user-no-comment')}</p>
}
My comment History
</TabContent>
<TabContent show={activeTab === 1}>
<BioContainer bio={userData.settings.bio} handleSave={this.handleSave} {...this.props} />
@@ -77,13 +58,11 @@ class SettingsContainer extends Component {
}
const mapStateToProps = state => ({
items: state.items.toJS(),
user: state.user.toJS()
});
const mapDispatchToProps = dispatch => ({
saveBio: (user_id, formData) => dispatch(saveBio(user_id, formData)),
fetchCommentsByUserId: userId => dispatch(fetchCommentsByUserId(userId))
saveBio: (user_id, formData) => dispatch(saveBio(user_id, formData))
});
export default connect(