old client structure
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const LOCALSTORAGE_AUTH_KEY = 'habit-mobile-settings';
|
||||
|
||||
export async function register (store, params) {
|
||||
let url = '/api/v4/user/auth/local/register';
|
||||
|
||||
if (params.groupInvite) url += `?groupInvite=${params.groupInvite}`;
|
||||
|
||||
let result = await axios.post(url, {
|
||||
username: params.username,
|
||||
email: params.email,
|
||||
password: params.password,
|
||||
confirmPassword: params.passwordConfirm,
|
||||
});
|
||||
|
||||
let user = result.data.data;
|
||||
|
||||
let userLocalData = JSON.stringify({
|
||||
auth: {
|
||||
apiId: user._id,
|
||||
apiToken: user.apiToken,
|
||||
},
|
||||
});
|
||||
localStorage.setItem(LOCALSTORAGE_AUTH_KEY, userLocalData);
|
||||
}
|
||||
|
||||
export async function login (store, params) {
|
||||
let url = '/api/v4/user/auth/local/login';
|
||||
let result = await axios.post(url, {
|
||||
username: params.username,
|
||||
// email: params.email,
|
||||
password: params.password,
|
||||
});
|
||||
|
||||
let user = result.data.data;
|
||||
|
||||
let userLocalData = JSON.stringify({
|
||||
auth: {
|
||||
apiId: user.id,
|
||||
apiToken: user.apiToken,
|
||||
},
|
||||
});
|
||||
|
||||
localStorage.setItem(LOCALSTORAGE_AUTH_KEY, userLocalData);
|
||||
}
|
||||
|
||||
export async function verifyUsername (store, params) {
|
||||
let url = '/api/v4/user/auth/verify-username';
|
||||
let result = await axios.post(url, {
|
||||
username: params.username,
|
||||
});
|
||||
|
||||
return result.data.data;
|
||||
}
|
||||
|
||||
export async function verifyDisplayName (store, params) {
|
||||
let url = '/api/v4/user/auth/verify-display-name';
|
||||
let result = await axios.post(url, {
|
||||
displayName: params.displayName,
|
||||
});
|
||||
|
||||
return result.data.data;
|
||||
}
|
||||
|
||||
export async function socialAuth (store, params) {
|
||||
let url = '/api/v4/user/auth/social';
|
||||
let result = await axios.post(url, {
|
||||
network: params.auth.network,
|
||||
authResponse: params.auth.authResponse,
|
||||
});
|
||||
|
||||
let user = result.data.data;
|
||||
|
||||
let userLocalData = JSON.stringify({
|
||||
auth: {
|
||||
apiId: user.id,
|
||||
apiToken: user.apiToken,
|
||||
},
|
||||
});
|
||||
|
||||
localStorage.setItem(LOCALSTORAGE_AUTH_KEY, userLocalData);
|
||||
}
|
||||
|
||||
export function logout () {
|
||||
localStorage.clear();
|
||||
window.location.href = '/logout-server';
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import axios from 'axios';
|
||||
import omit from 'lodash/omit';
|
||||
import encodeParams from 'client/libs/encodeParams';
|
||||
|
||||
export async function createChallenge (store, payload) {
|
||||
let response = await axios.post('/api/v4/challenges', payload.challenge);
|
||||
let newChallenge = response.data.data;
|
||||
|
||||
return newChallenge;
|
||||
}
|
||||
|
||||
export async function cloneChallenge (store, payload) {
|
||||
const response = await axios.post(`/api/v4/challenges/${payload.cloningChallengeId}/clone`, payload.challenge);
|
||||
const newChallenge = response.data.data.clonedChallenge;
|
||||
|
||||
return newChallenge;
|
||||
}
|
||||
|
||||
export async function joinChallenge (store, payload) {
|
||||
let response = await axios.post(`/api/v4/challenges/${payload.challengeId}/join`);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function leaveChallenge (store, payload) {
|
||||
let url = `/api/v4/challenges/${payload.challengeId}/leave`;
|
||||
let response = await axios.post(url, {
|
||||
keep: payload.keep,
|
||||
});
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getUserChallenges (store, payload) {
|
||||
let url = '/api/v4/challenges/user';
|
||||
let {
|
||||
member,
|
||||
page,
|
||||
search,
|
||||
categories,
|
||||
owned,
|
||||
} = payload;
|
||||
|
||||
let query = {};
|
||||
if (member) query.member = member;
|
||||
if (page >= 0) query.page = page;
|
||||
if (search) query.search = search;
|
||||
if (categories) query.categories = categories;
|
||||
if (owned) query.owned = owned;
|
||||
|
||||
const parms = encodeParams(query);
|
||||
const response = await axios.get(`${url}?${parms}`);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getGroupChallenges (store, payload) {
|
||||
let response = await axios.get(`/api/v4/challenges/groups/${payload.groupId}`);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getChallenge (store, payload) {
|
||||
let response = await axios.get(`/api/v4/challenges/${payload.challengeId}`);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function exportChallengeCsv (store, payload) {
|
||||
let response = await axios.get(`/api/v4/challenges/${payload.challengeId}/export/csv`);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
|
||||
export async function updateChallenge (store, payload) {
|
||||
let challengeDataToSend = omit(payload.challenge, ['tasks', 'habits', 'todos', 'rewards', 'group']);
|
||||
|
||||
if (challengeDataToSend.leader && challengeDataToSend.leader._id) challengeDataToSend.leader = challengeDataToSend.leader._id;
|
||||
|
||||
let response = await axios.put(`/api/v4/challenges/${payload.challenge._id}`, challengeDataToSend);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function deleteChallenge (store, payload) {
|
||||
const response = await axios.delete(`/api/v4/challenges/${payload.challengeId}`);
|
||||
if (payload.prize) {
|
||||
store.state.user.data.balance += payload.prize / 4;
|
||||
}
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function selectChallengeWinner (store, payload) {
|
||||
let response = await axios.post(`/api/v4/challenges/${payload.challengeId}/selectWinner/${payload.winnerId}`);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import axios from 'axios';
|
||||
import * as Analytics from 'client/libs/analytics';
|
||||
|
||||
export async function getChat (store, payload) {
|
||||
let response = await axios.get(`/api/v4/groups/${payload.groupId}/chat`);
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function postChat (store, payload) {
|
||||
const group = payload.group;
|
||||
|
||||
let url = `/api/v4/groups/${group._id}/chat`;
|
||||
|
||||
if (payload.previousMsg) {
|
||||
url += `?previousMsg=${payload.previousMsg}`;
|
||||
}
|
||||
|
||||
if (group.type === 'party') {
|
||||
Analytics.updateUser({
|
||||
partyID: group.id,
|
||||
partySize: group.memberCount,
|
||||
});
|
||||
}
|
||||
|
||||
let response = await axios.post(url, {
|
||||
message: payload.message,
|
||||
});
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function deleteChat (store, payload) {
|
||||
let url = `/api/v4/groups/${payload.groupId}/chat/${payload.chatId}`;
|
||||
|
||||
if (payload.previousMsg) {
|
||||
url += `?previousMsg=${payload.previousMsg}`;
|
||||
}
|
||||
|
||||
let response = await axios.delete(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function like (store, payload) {
|
||||
let url = `/api/v4/groups/${payload.groupId}/chat/${payload.chatId}/like`;
|
||||
let response = await axios.post(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function flag (store, payload) {
|
||||
let url = '';
|
||||
|
||||
if (payload.groupId === 'privateMessage') {
|
||||
url = `/api/v4/members/flag-private-message/${payload.chatId}`;
|
||||
} else {
|
||||
url = `/api/v4/groups/${payload.groupId}/chat/${payload.chatId}/flag`;
|
||||
}
|
||||
|
||||
const response = await axios.post(url, {
|
||||
comment: payload.comment,
|
||||
});
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function clearFlagCount (store, payload) {
|
||||
let url = `/api/v4/groups/${payload.groupId}/chat/${payload.chatId}/clearflags`;
|
||||
let response = await axios.post(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function markChatSeen (store, payload) {
|
||||
if (store.state.user.newMessages) delete store.state.user.newMessages[payload.groupId];
|
||||
let url = `/api/v4/groups/${payload.groupId}/chat/seen`;
|
||||
let response = await axios.post(url);
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import axios from 'axios';
|
||||
import equipOp from 'common/script/ops/equip';
|
||||
import hatchOp from 'common/script/ops/hatch';
|
||||
import feedOp from 'common/script/ops/feed';
|
||||
|
||||
export function equip (store, params) {
|
||||
const user = store.state.user.data;
|
||||
equipOp(user, {params});
|
||||
axios
|
||||
.post(`/api/v4/user/equip/${params.type}/${params.key}`);
|
||||
// TODO
|
||||
// .then((res) => console.log('equip', res))
|
||||
// .catch((err) => console.error('equip', err));
|
||||
}
|
||||
|
||||
export function hatch (store, params) {
|
||||
const user = store.state.user.data;
|
||||
hatchOp(user, {params});
|
||||
axios
|
||||
.post(`/api/v4/user/hatch/${params.egg}/${params.hatchingPotion}`);
|
||||
// TODO
|
||||
// .then((res) => console.log('equip', res))
|
||||
// .catch((err) => console.error('equip', err));
|
||||
}
|
||||
|
||||
export async function feed (store, params) {
|
||||
const user = store.state.user.data;
|
||||
feedOp(user, {params});
|
||||
const response = await axios
|
||||
.post(`/api/v4/user/feed/${params.pet}/${params.food}`);
|
||||
return response.data;
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
import axios from 'axios';
|
||||
import omit from 'lodash/omit';
|
||||
import findIndex from 'lodash/findIndex';
|
||||
import * as Analytics from 'client/libs/analytics';
|
||||
|
||||
export async function getPublicGuilds (store, payload) {
|
||||
let params = {
|
||||
type: 'publicGuilds',
|
||||
paginate: true,
|
||||
page: payload.page,
|
||||
};
|
||||
|
||||
if (payload.categories) params.categories = payload.categories;
|
||||
if (payload.minMemberCount) params.minMemberCount = payload.minMemberCount;
|
||||
if (payload.maxMemberCount) params.maxMemberCount = payload.maxMemberCount;
|
||||
if (payload.leader) params.leader = payload.leader;
|
||||
if (payload.member) params.member = payload.member;
|
||||
if (payload.search) params.search = payload.search;
|
||||
|
||||
let response = await axios.get('/api/v4/groups', {
|
||||
params,
|
||||
});
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getMyGuilds (store) {
|
||||
let params = {
|
||||
type: 'guilds',
|
||||
};
|
||||
|
||||
let response = await axios.get('/api/v4/groups', { params });
|
||||
|
||||
let guilds = response.data.data;
|
||||
store.state.myGuilds = guilds;
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getGroup (store, payload) {
|
||||
let response = await axios.get(`/api/v4/groups/${payload.groupId}`);
|
||||
// @TODO: should we store the active group for modifying?
|
||||
// let guilds = response.data.data;
|
||||
// store.state.myGuilds = guilds;
|
||||
|
||||
// @TODO: Populate with members, challenges, and invites
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
|
||||
export async function join (store, payload) {
|
||||
const groupId = payload.groupId;
|
||||
const type = payload.type;
|
||||
const user = store.state.user.data;
|
||||
const invitations = user.invitations;
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await axios.post(`/api/v4/groups/${groupId}/join`);
|
||||
} catch (err) {
|
||||
alert(err.response.data.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'guild') {
|
||||
const invitationI = invitations.guilds.findIndex(i => i.id === groupId);
|
||||
if (invitationI !== -1) invitations.guilds.splice(invitationI, 1);
|
||||
|
||||
user.guilds.push(groupId);
|
||||
store.state.myGuilds.push(response.data.data);
|
||||
} else if (type === 'party') {
|
||||
const invitationI = invitations.parties.findIndex(i => i.id === groupId);
|
||||
if (invitationI !== -1) invitations.parties.splice(invitationI, 1);
|
||||
|
||||
user.party._id = groupId;
|
||||
|
||||
Analytics.updateUser({partyID: groupId});
|
||||
}
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function leave (store, payload) {
|
||||
// @TODO: is the dafault for keepChallenges 'remain-in-challenges'
|
||||
let data = {
|
||||
keep: payload.keep,
|
||||
keepChallenges: payload.keepChallenges,
|
||||
};
|
||||
let response = await axios.post(`/api/v4/groups/${payload.groupId}/leave`, data);
|
||||
|
||||
// @TODO: update for party
|
||||
let index = store.state.user.data.guilds.indexOf(payload.groupId);
|
||||
store.state.user.data.guilds.splice(index, 1);
|
||||
if (payload.type === 'myGuilds') {
|
||||
let guildIndex = findIndex(store.state.myGuilds, (guild) => {
|
||||
return guild._id === payload.groupId;
|
||||
});
|
||||
store.state.myGuilds.splice(guildIndex, 1);
|
||||
} else if (payload.type === 'party') {
|
||||
store.state.user.data.party._id = null;
|
||||
store.state.party.data = {};
|
||||
store.state.party.status = 'NOT_LOADED';
|
||||
}
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function create (store, payload) {
|
||||
let response = await axios.post('/api/v4/groups/', payload.group);
|
||||
let newGroup = response.data.data;
|
||||
|
||||
if (newGroup.leader._id === store.state.user.data._id || newGroup.privacy === 'private') {
|
||||
store.state.myGuilds.push(newGroup);
|
||||
}
|
||||
|
||||
store.state.user.data.guilds.push(newGroup._id);
|
||||
|
||||
return newGroup;
|
||||
}
|
||||
|
||||
export async function update (store, payload) {
|
||||
// Remove populated fields
|
||||
let groupDetailsToSend = omit(payload.group, ['chat', 'challenges', 'members', 'invites']);
|
||||
if (groupDetailsToSend.leader && groupDetailsToSend.leader._id) groupDetailsToSend.leader = groupDetailsToSend.leader._id;
|
||||
|
||||
let response = await axios.put(`/api/v4/groups/${payload.group.id}`, groupDetailsToSend);
|
||||
|
||||
let updatedGroup = response.data.data;
|
||||
|
||||
return updatedGroup;
|
||||
}
|
||||
|
||||
export async function rejectInvite (store, payload) {
|
||||
const groupId = payload.groupId;
|
||||
const type = payload.type;
|
||||
const user = store.state.user.data;
|
||||
const invitations = user.invitations;
|
||||
|
||||
let response = await axios.post(`/api/v4/groups/${groupId}/reject-invite`);
|
||||
|
||||
if (type === 'guild') {
|
||||
const invitationI = invitations.guilds.findIndex(i => i.id === groupId);
|
||||
if (invitationI !== -1) invitations.guilds.splice(invitationI, 1);
|
||||
} else if (type === 'party') {
|
||||
const invitationI = invitations.parties.findIndex(i => i.id === groupId);
|
||||
if (invitationI !== -1) invitations.parties.splice(invitationI, 1);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function removeMember (store, payload) {
|
||||
let response = await axios.post(`/api/v4/groups/${payload.groupId}/removeMember/${payload.memberId}`, {
|
||||
message: payload.message,
|
||||
});
|
||||
|
||||
// @TODO: find guild and remove member
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function invite (store, payload) {
|
||||
let response = await axios.post(`/api/v4/groups/${payload.groupId}/invite`, {
|
||||
uuids: payload.invitationDetails.uuids,
|
||||
emails: payload.invitationDetails.emails,
|
||||
usernames: payload.invitationDetails.usernames,
|
||||
});
|
||||
|
||||
// @TODO: find guild and add invites
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function inviteToQuest (store, payload) {
|
||||
let response = await axios.post(`/api/v4/groups/${payload.groupId}/quests/invite/${payload.key}`);
|
||||
|
||||
// @TODO: Any updates?
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function addManager (store, payload) {
|
||||
let response = await axios.post(`/api/v4/groups/${payload.groupId}/add-manager/`, {
|
||||
managerId: payload.memberId,
|
||||
});
|
||||
|
||||
// @TODO: Add managers to group or does the component handle?
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function removeManager (store, payload) {
|
||||
let response = await axios.post(`/api/v4/groups/${payload.groupId}/remove-manager/`, {
|
||||
managerId: payload.memberId,
|
||||
});
|
||||
|
||||
// @TODO: Add managers to group or does the component handle?
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function getGroupPlans () {
|
||||
let response = await axios.get('/api/v4/group-plans');
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export async function getHeroes () {
|
||||
let url = '/api/v4/hall/heroes';
|
||||
let response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getHero (store, payload) {
|
||||
let url = `/api/v4/hall/heroes/${payload.uuid}`;
|
||||
let response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function updateHero (store, payload) {
|
||||
let url = `/api/v4/hall/heroes/${payload.heroDetails._id}`;
|
||||
let response = await axios.put(url, payload.heroDetails);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getPatrons (store, payload) {
|
||||
let page = 0;
|
||||
if (payload.page) page = payload.page;
|
||||
|
||||
let url = `/api/v4/hall/patrons/?page=${page}`;
|
||||
let response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { flattenAndNamespace } from 'client/libs/store/helpers/internals';
|
||||
|
||||
import * as common from './common';
|
||||
import * as user from './user';
|
||||
import * as tasks from './tasks';
|
||||
import * as guilds from './guilds';
|
||||
import * as party from './party';
|
||||
import * as members from './members';
|
||||
import * as auth from './auth';
|
||||
import * as quests from './quests';
|
||||
import * as challenges from './challenges';
|
||||
import * as chat from './chat';
|
||||
import * as notifications from './notifications';
|
||||
import * as tags from './tags';
|
||||
import * as hall from './hall';
|
||||
import * as shops from './shops';
|
||||
import * as snackbars from './snackbars';
|
||||
import * as worldState from './world-state';
|
||||
|
||||
// Actions should be named as 'actionName' and can be accessed as 'namespace:actionName'
|
||||
// Example: fetch in user.js -> 'user:fetch'
|
||||
|
||||
const actions = flattenAndNamespace({
|
||||
common,
|
||||
user,
|
||||
tasks,
|
||||
guilds,
|
||||
party,
|
||||
members,
|
||||
auth,
|
||||
quests,
|
||||
challenges,
|
||||
chat,
|
||||
notifications,
|
||||
tags,
|
||||
hall,
|
||||
shops,
|
||||
snackbars,
|
||||
worldState,
|
||||
});
|
||||
|
||||
export default actions;
|
||||
@@ -0,0 +1,134 @@
|
||||
import axios from 'axios';
|
||||
// import omit from 'lodash/omit';
|
||||
// import findIndex from 'lodash/findIndex';
|
||||
|
||||
let apiv4Prefix = '/api/v4';
|
||||
|
||||
export async function getGroupMembers (store, payload) {
|
||||
let url = `${apiv4Prefix}/groups/${payload.groupId}/members`;
|
||||
|
||||
const params = {};
|
||||
|
||||
if (payload.includeAllPublicFields) {
|
||||
params.includeAllPublicFields = true;
|
||||
}
|
||||
|
||||
if (payload.lastMemberId) {
|
||||
params.lastId = payload.lastMemberId;
|
||||
}
|
||||
|
||||
if (payload.searchTerm) {
|
||||
params.search = payload.searchTerm;
|
||||
}
|
||||
|
||||
let response = await axios.get(url, { params });
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function fetchMember (store, payload) {
|
||||
let url = `${apiv4Prefix}/members/${payload.memberId}`;
|
||||
let response = await axios.get(url);
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function getGroupInvites (store, payload) {
|
||||
let url = `${apiv4Prefix}/groups/${payload.groupId}/invites`;
|
||||
if (payload.includeAllPublicFields) {
|
||||
url += '?includeAllPublicFields=true';
|
||||
}
|
||||
let response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getChallengeMembers (store, payload) {
|
||||
let url = `${apiv4Prefix}/challenges/${payload.challengeId}/members`;
|
||||
|
||||
const params = {};
|
||||
|
||||
if (payload.includeAllPublicFields) {
|
||||
params.includeAllPublicFields = true;
|
||||
}
|
||||
|
||||
if (payload.lastMemberId) {
|
||||
params.lastId = payload.lastMemberId;
|
||||
}
|
||||
|
||||
if (payload.searchTerm) {
|
||||
params.search = payload.searchTerm;
|
||||
}
|
||||
|
||||
let response = await axios.get(url, { params });
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getChallengeMemberProgress (store, payload) {
|
||||
let url = `${apiv4Prefix}/challenges/${payload.challengeId}/members/${payload.memberId}`;
|
||||
let response = await axios.get(url);
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function sendPrivateMessage (store, payload) {
|
||||
let url = `${apiv4Prefix}/members/send-private-message`;
|
||||
let data = {
|
||||
message: payload.message,
|
||||
toUserId: payload.toUserId,
|
||||
};
|
||||
let response = await axios.post(url, data);
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function transferGems (store, payload) {
|
||||
let url = `${apiv4Prefix}/members/transfer-gems`;
|
||||
let data = {
|
||||
message: payload.message,
|
||||
toUserId: payload.toUserId,
|
||||
gemAmount: payload.gemAmount,
|
||||
};
|
||||
let response = await axios.post(url, data);
|
||||
store.state.user.data.balance -= payload.gemAmount / 4;
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function removeMember (store, payload) {
|
||||
let url = `${apiv4Prefix}/groups/${payload.groupId}/removeMember/${payload.memberId}`;
|
||||
let data = {
|
||||
message: payload.message,
|
||||
};
|
||||
let response = await axios.post(url, data);
|
||||
return response;
|
||||
}
|
||||
|
||||
// export async function selectMember (uid) {
|
||||
// let memberIsReady = _checkIfMemberIsReady(members[uid]);
|
||||
//
|
||||
// if (memberIsReady) {
|
||||
// _prepareMember(members[uid], self);
|
||||
// return
|
||||
// } else {
|
||||
// fetchMember(uid)
|
||||
// .then(function (response) {
|
||||
// var member = response.data.data;
|
||||
// addToMembersList(member); // lazy load for later
|
||||
// _prepareMember(member, self);
|
||||
// deferred.resolve();
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// function addToMembersList (member) {
|
||||
// if (member._id) {
|
||||
// members[member._id] = member;
|
||||
// }
|
||||
// }
|
||||
|
||||
// function _checkIfMemberIsReady (member) {
|
||||
// return member && member.items && member.items.weapon;
|
||||
// }
|
||||
//
|
||||
// function _prepareMember(member, self) {
|
||||
// self.selectedMember = members[member._id];
|
||||
// }
|
||||
//
|
||||
// $rootScope.$on('userUpdated', function(event, user){
|
||||
// addToMembersList(user);
|
||||
// })
|
||||
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export async function readNotification (store, payload) {
|
||||
let url = `/api/v4/notifications/${payload.notificationId}/read`;
|
||||
let response = await axios.post(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function readNotifications (store, payload) {
|
||||
let url = '/api/v4/notifications/read';
|
||||
let response = await axios.post(url, {
|
||||
notificationIds: payload.notificationIds,
|
||||
});
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function seeNotification (store, payload) {
|
||||
let url = `/api/v4/notifications/${payload.notificationId}/see`;
|
||||
let response = await axios.post(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function seeNotifications (store, payload) {
|
||||
let url = '/api/v4/notifications/see';
|
||||
let response = await axios.post(url, {
|
||||
notificationIds: payload.notificationIds,
|
||||
});
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { loadAsyncResource } from 'client/libs/asyncResource';
|
||||
|
||||
export function getMembers (store, forceLoad = false) {
|
||||
return loadAsyncResource({
|
||||
store,
|
||||
path: 'partyMembers',
|
||||
url: '/api/v4/groups/party/members?includeAllPublicFields=true',
|
||||
deserialize (response) {
|
||||
return response.data.data;
|
||||
},
|
||||
forceLoad,
|
||||
});
|
||||
}
|
||||
|
||||
export function getParty (store, forceLoad = false) {
|
||||
return loadAsyncResource({
|
||||
store,
|
||||
path: 'party',
|
||||
url: '/api/v4/groups/party',
|
||||
deserialize (response) {
|
||||
return response.data.data;
|
||||
},
|
||||
forceLoad,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import axios from 'axios';
|
||||
import * as Analytics from 'client/libs/analytics';
|
||||
|
||||
// export async function initQuest (store) {
|
||||
// }
|
||||
|
||||
export async function sendAction (store, payload) {
|
||||
// @TODO: Maybe move this to server
|
||||
let partyData = {};
|
||||
if (store.state.party && store.state.party.data) {
|
||||
partyData = {
|
||||
partyID: store.state.party.data._id,
|
||||
partySize: store.state.party.data.memberCount,
|
||||
};
|
||||
} else {
|
||||
partyData = {
|
||||
partyID: store.state.user.data.party._id,
|
||||
partySize: store.state.partyMembers.data.length,
|
||||
};
|
||||
}
|
||||
|
||||
Analytics.updateUser(partyData);
|
||||
|
||||
let response = await axios.post(`/api/v4/groups/${payload.groupId}/${payload.action}`);
|
||||
|
||||
// @TODO: Update user?
|
||||
// User.sync();
|
||||
|
||||
return response.data.quest || response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import axios from 'axios';
|
||||
import buyOp from 'common/script/ops/buy/buy';
|
||||
import content from 'common/script/content/index';
|
||||
import hourglassPurchaseOp from 'common/script/ops/buy/hourglassPurchase';
|
||||
import sellOp from 'common/script/ops/sell';
|
||||
import unlockOp from 'common/script/ops/unlock';
|
||||
import rerollOp from 'common/script/ops/reroll';
|
||||
import releasePetsOp from 'common/script/ops/releasePets';
|
||||
import releaseMountsOp from 'common/script/ops/releaseMounts';
|
||||
import releaseBothOp from 'common/script/ops/releaseBoth';
|
||||
|
||||
import { getDropClass } from 'client/libs/notifications';
|
||||
|
||||
// @TODO: Purchase means gems and buy means gold. That wording is misused below, but we should also change
|
||||
// the generic buy functions to something else. Or have a Gold Vendor and Gem Vendor, etc
|
||||
|
||||
function buyItem (store, params) {
|
||||
const quantity = params.quantity || 1;
|
||||
const user = store.state.user.data;
|
||||
|
||||
let opResult = buyOp(user, {params, quantity});
|
||||
|
||||
return {
|
||||
result: opResult,
|
||||
httpCall: axios.post(`/api/v4/user/buy/${params.key}`),
|
||||
};
|
||||
}
|
||||
|
||||
export function buyQuestItem (store, params) {
|
||||
const quantity = params.quantity || 1;
|
||||
const user = store.state.user.data;
|
||||
let opResult = buyOp(user, {
|
||||
params,
|
||||
type: 'quest',
|
||||
quantity,
|
||||
});
|
||||
|
||||
return {
|
||||
result: opResult,
|
||||
httpCall: axios.post(`/api/v4/user/buy/${params.key}`, {type: 'quest', quantity}),
|
||||
};
|
||||
}
|
||||
|
||||
async function buyArmoire (store, params) {
|
||||
const quantity = params.quantity || 1;
|
||||
let armoire = content.armoire;
|
||||
|
||||
// We need the server result because Armoire has random item in the result
|
||||
let result = await axios.post('/api/v4/user/buy/armoire', {
|
||||
type: 'armoire',
|
||||
quantity,
|
||||
});
|
||||
let buyResult = result.data.data;
|
||||
|
||||
if (buyResult) {
|
||||
const resData = buyResult;
|
||||
const item = resData.armoire;
|
||||
const message = result.data.message;
|
||||
|
||||
const isExperience = item.type === 'experience';
|
||||
if (item.type === 'gear') {
|
||||
store.state.user.data.items.gear.owned[item.dropKey] = true;
|
||||
}
|
||||
|
||||
if (item.type === 'food') {
|
||||
if (!store.state.user.data.items.food[item.dropKey]) store.state.user.data.items.food[item.dropKey] = 0;
|
||||
store.state.user.data.items.food[item.dropKey] += 1;
|
||||
}
|
||||
|
||||
store.state.user.data.stats.gp -= armoire.value;
|
||||
|
||||
// @TODO: We might need to abstract notifications to library rather than mixin
|
||||
const notificationOptions = isExperience ?
|
||||
{
|
||||
text: `+ ${item.value}`,
|
||||
type: 'xp',
|
||||
flavorMessage: message,
|
||||
} :
|
||||
{
|
||||
text: message,
|
||||
type: 'drop',
|
||||
icon: getDropClass({type: item.type, key: item.dropKey}),
|
||||
};
|
||||
|
||||
store.dispatch('snackbars:add', {
|
||||
title: '',
|
||||
timeout: true,
|
||||
...notificationOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function purchase (store, params) {
|
||||
const quantity = params.quantity || 1;
|
||||
const user = store.state.user.data;
|
||||
let opResult = buyOp(user, {params, quantity});
|
||||
|
||||
return {
|
||||
result: opResult,
|
||||
httpCall: axios.post(`/api/v4/user/purchase/${params.type}/${params.key}`, {quantity}),
|
||||
};
|
||||
}
|
||||
|
||||
export function purchaseMysterySet (store, params) {
|
||||
const user = store.state.user.data;
|
||||
let opResult = buyOp(user, {params, type: 'mystery'});
|
||||
|
||||
return {
|
||||
result: opResult,
|
||||
httpCall: axios.post(`/api/v4/user/buy/${params.key}`, {type: 'mystery'}),
|
||||
};
|
||||
}
|
||||
|
||||
export function purchaseHourglassItem (store, params) {
|
||||
const quantity = params.quantity || 1;
|
||||
const user = store.state.user.data;
|
||||
let opResult = hourglassPurchaseOp(user, {params, quantity});
|
||||
|
||||
return {
|
||||
result: opResult,
|
||||
httpCall: axios.post(`/api/v4/user/purchase-hourglass/${params.type}/${params.key}`, {quantity}),
|
||||
};
|
||||
}
|
||||
|
||||
export function unlock (store, params) {
|
||||
const user = store.state.user.data;
|
||||
let opResult = unlockOp(user, params);
|
||||
|
||||
return {
|
||||
result: opResult,
|
||||
httpCall: axios.post(`/api/v4/user/unlock?path=${params.query.path}`),
|
||||
};
|
||||
}
|
||||
|
||||
export async function genericPurchase (store, params) {
|
||||
switch (params.pinType) {
|
||||
case 'mystery_set':
|
||||
return purchaseMysterySet(store, params);
|
||||
case 'armoire': // eslint-disable-line
|
||||
await buyArmoire(store, params);
|
||||
return;
|
||||
case 'fortify': {
|
||||
let rerollResult = rerollOp(store.state.user.data, store.state.tasks.data);
|
||||
|
||||
await axios.post('/api/v4/user/reroll');
|
||||
await Promise.all([
|
||||
store.dispatch('user:fetch', {forceLoad: true}),
|
||||
store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
|
||||
]);
|
||||
|
||||
return rerollResult;
|
||||
}
|
||||
case 'rebirth_orb':
|
||||
return store.dispatch('user:rebirth');
|
||||
case 'potion':
|
||||
case 'marketGear':
|
||||
// 'marketGear' gets `type`= `gear` which is used for gem-purchasable gear
|
||||
// resetting type to pinType only here
|
||||
return buyItem(store, {...params, type: params.pinType});
|
||||
case 'background':
|
||||
return unlock(store, {
|
||||
query: {
|
||||
path: `background.${params.key}`,
|
||||
},
|
||||
});
|
||||
default:
|
||||
if (params.pinType === 'quests' && params.currency === 'gold') {
|
||||
return buyQuestItem(store, params);
|
||||
} else if (params.currency === 'hourglasses') {
|
||||
return purchaseHourglassItem(store, params);
|
||||
} else {
|
||||
return purchase(store, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function sellItems (store, params) {
|
||||
const user = store.state.user.data;
|
||||
sellOp(user, {params, query: {amount: params.amount}});
|
||||
axios.post(`/api/v4/user/sell/${params.type}/${params.key}?amount=${params.amount}`);
|
||||
}
|
||||
|
||||
export function releasePets (store, params) {
|
||||
releasePetsOp(params.user);
|
||||
axios.post('/api/v4/user/release-pets');
|
||||
}
|
||||
|
||||
export function releaseMounts (store, params) {
|
||||
releaseMountsOp(params.user);
|
||||
axios.post('/api/v4/user/release-mounts');
|
||||
}
|
||||
|
||||
export function releaseBoth (store, params) {
|
||||
releaseBothOp(params.user);
|
||||
axios.post('/api/v4/user/release-both');
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import uuid from 'uuid';
|
||||
|
||||
export function add (store, payload) {
|
||||
let notification = Object.assign({}, payload);
|
||||
notification.uuid = uuid();
|
||||
store.state.notificationStore.push(notification);
|
||||
}
|
||||
|
||||
export function remove (store, payload) {
|
||||
store.state.notificationStore = store.state.notificationStore.filter(notification => {
|
||||
return notification.uuid !== payload.uuid;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export async function getTags () {
|
||||
let url = 'api/v4/tags';
|
||||
let response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function createTag (store, payload) {
|
||||
let url = 'api/v4/tags';
|
||||
let response = await axios.post(url, {
|
||||
tagDetails: payload.tagDetails,
|
||||
});
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getTag (store, payload) {
|
||||
let url = `api/v4/tags/${payload.tagId}`;
|
||||
let response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function updateTag (store, payload) {
|
||||
let url = `api/v4/tags/${payload.tagId}`;
|
||||
let response = await axios.put(url, {
|
||||
tagDetails: payload.tagDetails,
|
||||
});
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function sortTag (store, payload) {
|
||||
let url = 'api/v4/reorder-tags';
|
||||
let response = await axios.post(url, {
|
||||
tagId: payload.tagId,
|
||||
to: payload.to,
|
||||
});
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function deleteTag (store, payload) {
|
||||
let url = `api/v4/tags/${payload.tagId}`;
|
||||
let response = await axios.delete(url);
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
import { loadAsyncResource } from 'client/libs/asyncResource';
|
||||
import axios from 'axios';
|
||||
import compact from 'lodash/compact';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
export function fetchUserTasks (store, options = {}) {
|
||||
return loadAsyncResource({
|
||||
store,
|
||||
path: 'tasks',
|
||||
url: '/api/v4/tasks/user',
|
||||
deserialize (response) {
|
||||
// Wait for the user to be loaded before deserializing
|
||||
// because user.tasksOrder is necessary
|
||||
return store.dispatch('user:fetch').then((userResource) => {
|
||||
return store.dispatch('tasks:order', [response.data.data, userResource.data.tasksOrder]);
|
||||
});
|
||||
},
|
||||
forceLoad: options.forceLoad,
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchCompletedTodos (store) {
|
||||
// Wait for the user to be loaded before deserializing
|
||||
// because user.tasksOrder is necessary
|
||||
await store.dispatch('tasks:fetchUserTasks');
|
||||
|
||||
const loadStatus = store.state.completedTodosStatus;
|
||||
if (loadStatus !== 'LOADING') {
|
||||
store.state.completedTodosStatus = 'LOADING';
|
||||
|
||||
const response = await axios.get('/api/v4/tasks/user?type=completedTodos');
|
||||
const completedTodos = response.data.data;
|
||||
const tasks = store.state.tasks.data;
|
||||
// Remove existing completed todos
|
||||
tasks.todos = tasks.todos.filter(t => !t.completed);
|
||||
tasks.todos.push(...completedTodos);
|
||||
|
||||
store.state.completedTodosStatus = 'LOADED';
|
||||
}
|
||||
}
|
||||
|
||||
export async function clearCompletedTodos (store) {
|
||||
await axios.post('/api/v4/tasks/clearCompletedTodos');
|
||||
store.state.tasks.data.todos = store.state.tasks.data.todos.filter(task => {
|
||||
return !task.completed;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function order (store, [rawTasks, tasksOrder]) {
|
||||
const tasks = {
|
||||
habits: [],
|
||||
dailys: [],
|
||||
todos: [],
|
||||
rewards: [],
|
||||
};
|
||||
|
||||
rawTasks.forEach(task => {
|
||||
tasks[`${task.type}s`].push(task);
|
||||
});
|
||||
|
||||
Object.keys(tasks).forEach((type) => {
|
||||
let tasksOfType = tasks[type];
|
||||
|
||||
const orderOfType = tasksOrder[type];
|
||||
const orderedTasks = new Array(tasksOfType.length);
|
||||
const unorderedTasks = []; // what we want to add later
|
||||
|
||||
tasksOfType.forEach((task, index) => {
|
||||
const taskId = task._id;
|
||||
const i = orderOfType[index] === taskId ? index : orderOfType.indexOf(taskId);
|
||||
if (i === -1) {
|
||||
unorderedTasks.push(task);
|
||||
} else {
|
||||
orderedTasks[i] = task;
|
||||
}
|
||||
});
|
||||
|
||||
tasks[type] = compact(orderedTasks).concat(unorderedTasks);
|
||||
});
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
function sanitizeChecklist (task) {
|
||||
if (task.checklist) {
|
||||
task.checklist = task.checklist.filter((i) => {
|
||||
return Boolean(i.text);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Supply an array to create multiple tasks
|
||||
export async function create (store, createdTask) {
|
||||
// Treat all create actions as if we are adding multiple tasks
|
||||
const payload = Array.isArray(createdTask) ? createdTask : [createdTask];
|
||||
|
||||
payload.forEach(t => {
|
||||
const type = `${t.type}s`;
|
||||
const list = store.state.tasks.data[type];
|
||||
|
||||
sanitizeChecklist(t);
|
||||
|
||||
list.unshift(t);
|
||||
store.state.user.data.tasksOrder[type].unshift(t._id);
|
||||
});
|
||||
|
||||
const response = await axios.post('/api/v4/tasks/user', payload);
|
||||
const data = Array.isArray(response.data.data) ? response.data.data : [response.data.data];
|
||||
|
||||
data.forEach(taskRes => {
|
||||
const taskData = store.state.tasks.data[`${taskRes.type}s`].find(t => t._id === taskRes._id);
|
||||
Object.assign(taskData, taskRes);
|
||||
});
|
||||
}
|
||||
|
||||
export async function save (store, editedTask) {
|
||||
const taskId = editedTask._id;
|
||||
const type = editedTask.type;
|
||||
const originalTask = store.state.tasks.data[`${type}s`].find(t => t._id === taskId);
|
||||
|
||||
sanitizeChecklist(editedTask);
|
||||
|
||||
if (originalTask) Object.assign(originalTask, editedTask);
|
||||
|
||||
const taskDataToSend = omit(editedTask, ['history']);
|
||||
const response = await axios.put(`/api/v4/tasks/${taskId}`, taskDataToSend);
|
||||
if (originalTask) Object.assign(originalTask, response.data.data);
|
||||
}
|
||||
|
||||
export async function scoreChecklistItem (store, {taskId, itemId}) {
|
||||
await axios.post(`/api/v4/tasks/${taskId}/checklist/${itemId}/score`);
|
||||
}
|
||||
|
||||
export async function collapseChecklist (store, task) {
|
||||
task.collapseChecklist = !task.collapseChecklist;
|
||||
await axios.put(`/api/v4/tasks/${task._id}`, {
|
||||
collapseChecklist: task.collapseChecklist,
|
||||
});
|
||||
}
|
||||
|
||||
export async function destroy (store, task) {
|
||||
const list = store.state.tasks.data[`${task.type}s`];
|
||||
const taskIndex = list.findIndex(t => t._id === task._id);
|
||||
|
||||
if (taskIndex > -1) {
|
||||
list.splice(taskIndex, 1);
|
||||
}
|
||||
|
||||
await axios.delete(`/api/v4/tasks/${task._id}`);
|
||||
}
|
||||
|
||||
export async function getChallengeTasks (store, payload) {
|
||||
let response = await axios.get(`/api/v4/tasks/challenge/${payload.challengeId}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function createChallengeTasks (store, payload) {
|
||||
let response = await axios.post(`/api/v4/tasks/challenge/${payload.challengeId}`, payload.tasks);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getGroupTasks (store, payload) {
|
||||
let response = await axios.get(`/api/v4/tasks/group/${payload.groupId}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getCompletedGroupTasks (store, payload) {
|
||||
let response = await axios.get(`/api/v4/tasks/group/${payload.groupId}?type=completedTodos`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function createGroupTasks (store, payload) {
|
||||
let response = await axios.post(`/api/v4/tasks/group/${payload.groupId}`, payload.tasks);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function assignTask (store, payload) {
|
||||
let response = await axios.post(`/api/v4/tasks/${payload.taskId}/assign/${payload.userId}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function unassignTask (store, payload) {
|
||||
let response = await axios.post(`/api/v4/tasks/${payload.taskId}/unassign/${payload.userId}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function needsWork (store, payload) {
|
||||
let response = await axios.post(`/api/v4/tasks/${payload.taskId}/needs-work/${payload.userId}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function getGroupApprovals (store, payload) {
|
||||
let response = await axios.get(`/api/v4/approvals/group/${payload.groupId}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function approve (store, payload) {
|
||||
let response = await axios.post(`/api/v4/tasks/${payload.taskId}/approve/${payload.userId}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function unlinkOneTask (store, payload) {
|
||||
if (!payload.keep) payload.keep = 'keep';
|
||||
|
||||
let task = payload.task;
|
||||
const list = store.state.tasks.data[`${task.type}s`];
|
||||
const taskIndex = list.findIndex(t => t._id === task._id);
|
||||
|
||||
if (taskIndex > -1) {
|
||||
list.splice(taskIndex, 1);
|
||||
}
|
||||
|
||||
let response = await axios.post(`/api/v4/tasks/unlink-one/${payload.task._id}?keep=${payload.keep}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function unlinkAllTasks (store, payload) {
|
||||
if (!payload.keep) payload.keep = 'keep-all';
|
||||
let response = await axios.post(`/api/v4/tasks/unlink-all/${payload.challengeId}?keep=${payload.keep}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function move (store, payload) {
|
||||
let response = await axios.post(`/api/v4/tasks/${payload.taskId}/move/to/${payload.position}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function moveGroupTask (store, payload) {
|
||||
let response = await axios.post(`/api/v4/group-tasks/${payload.taskId}/move/to/${payload.position}`);
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
import { loadAsyncResource } from 'client/libs/asyncResource';
|
||||
import setProps from 'lodash/set';
|
||||
import axios from 'axios';
|
||||
|
||||
import { togglePinnedItem as togglePinnedItemOp } from 'common/script/ops/pinnedGearUtils';
|
||||
import changeClassOp from 'common/script/ops/changeClass';
|
||||
import disableClassesOp from 'common/script/ops/disableClasses';
|
||||
import openMysteryItemOp from 'common/script/ops/openMysteryItem';
|
||||
|
||||
export function fetch (store, options = {}) { // eslint-disable-line no-shadow
|
||||
return loadAsyncResource({
|
||||
store,
|
||||
path: 'user',
|
||||
url: '/api/v4/user',
|
||||
deserialize (response) {
|
||||
return response.data.data;
|
||||
},
|
||||
forceLoad: options.forceLoad,
|
||||
});
|
||||
}
|
||||
|
||||
export async function set (store, changes) {
|
||||
const user = store.state.user.data;
|
||||
|
||||
for (let key in changes) {
|
||||
if (key === 'tags') {
|
||||
// Keep challenge and group tags
|
||||
const oldTags = user.tags.filter(t => {
|
||||
return t.group;
|
||||
});
|
||||
|
||||
user.tags = changes[key].concat(oldTags);
|
||||
|
||||
// Remove deleted tags from tasks
|
||||
const userTasksByType = (await store.dispatch('tasks:fetchUserTasks')).data; // eslint-disable-line no-await-in-loop
|
||||
|
||||
Object.keys(userTasksByType).forEach(taskType => {
|
||||
userTasksByType[taskType].forEach(task => {
|
||||
const tagsIndexesToRemove = [];
|
||||
|
||||
task.tags.forEach((tagId, tagIndex) => {
|
||||
if (user.tags.find(tag => tag.id === tagId)) return; // eslint-disable-line max-nested-callbacks
|
||||
tagsIndexesToRemove.push(tagIndex);
|
||||
});
|
||||
|
||||
tagsIndexesToRemove.forEach(i => task.tags.splice(i, 1));
|
||||
});
|
||||
});
|
||||
} else {
|
||||
setProps(user, key, changes[key]);
|
||||
}
|
||||
}
|
||||
|
||||
let response = await axios.put('/api/v4/user', changes);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function sleep (store) {
|
||||
const user = store.state.user.data;
|
||||
|
||||
user.preferences.sleep = !user.preferences.sleep;
|
||||
|
||||
let response = await axios.post('/api/v4/user/sleep');
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function addWebhook (store, payload) {
|
||||
let response = await axios.post('/api/v4/user/webhook', payload.webhookInfo);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function updateWebhook (store, payload) {
|
||||
let response = await axios.put(`/api/v4/user/webhook/${payload.webhook.id}`, payload.webhook);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function deleteWebhook (store, payload) {
|
||||
let response = await axios.delete(`/api/v4/user/webhook/${payload.webhook.id}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function changeClass (store, params) {
|
||||
const user = store.state.user.data;
|
||||
|
||||
changeClassOp(user, params);
|
||||
user.flags.classSelected = true;
|
||||
|
||||
let response = await axios.post(`/api/v4/user/change-class?class=${params.query.class}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export async function disableClasses (store) {
|
||||
const user = store.state.user.data;
|
||||
|
||||
disableClassesOp(user);
|
||||
let response = await axios.post('/api/v4/user/disable-classes');
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export function togglePinnedItem (store, params) {
|
||||
const user = store.state.user.data;
|
||||
|
||||
let addedItem = togglePinnedItemOp(user, params);
|
||||
|
||||
axios.get(`/api/v4/user/toggle-pinned-item/${params.type}/${params.path}`);
|
||||
// TODO
|
||||
// .then((res) => console.log('equip', res))
|
||||
// .catch((err) => console.error('equip', err));
|
||||
|
||||
return addedItem;
|
||||
}
|
||||
|
||||
export async function movePinnedItem (store, params) {
|
||||
let response = await axios.post(`/api/v4/user/move-pinned-item/${params.path}/move/to/${params.position}`);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export function castSpell (store, params) {
|
||||
let spellUrl = `/api/v4/user/class/cast/${params.key}`;
|
||||
|
||||
const data = {};
|
||||
|
||||
if (params.targetId) spellUrl += `?targetId=${params.targetId}`;
|
||||
if (params.quantity) data.quantity = params.quantity;
|
||||
|
||||
return axios.post(spellUrl, data);
|
||||
}
|
||||
|
||||
export async function openMysteryItem (store) {
|
||||
let user = store.state.user.data;
|
||||
openMysteryItemOp(user);
|
||||
return axios.post('/api/v4/user/open-mystery-item');
|
||||
}
|
||||
|
||||
export function newStuffLater (store) {
|
||||
store.state.user.data.flags.newStuff = false;
|
||||
return axios.post('/api/v4/news/tell-me-later');
|
||||
}
|
||||
|
||||
export async function rebirth () {
|
||||
let result = await axios.post('/api/v4/user/rebirth');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function togglePrivateMessagesOpt (store) {
|
||||
let response = await axios.put('/api/v4/user',
|
||||
{
|
||||
'inbox.optOut': !store.state.user.data.inbox.optOut,
|
||||
}
|
||||
);
|
||||
store.state.user.data.inbox.optOut = !store.state.user.data.inbox.optOut;
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function userLookup (store, params) {
|
||||
let response;
|
||||
if (params.uuid) {
|
||||
response = await axios.get(`/api/v4/members/${params.uuid}`);
|
||||
}
|
||||
if (params.username) {
|
||||
response = await axios.get(`/api/v4/members/username/${params.username}`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export async function getWorldState () {
|
||||
const url = '/api/v4/world-state';
|
||||
const response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { flattenAndNamespace } from 'client/libs/store/helpers/internals';
|
||||
import * as user from './user';
|
||||
import * as shops from './shops';
|
||||
import * as tasks from './tasks';
|
||||
import * as party from './party';
|
||||
import * as members from './members';
|
||||
|
||||
// Getters should be named as 'getterName' and can be accessed as 'namespace:getterName'
|
||||
// Example: gems in user.js -> 'user:gems'
|
||||
|
||||
const getters = flattenAndNamespace({
|
||||
user,
|
||||
tasks,
|
||||
party,
|
||||
members,
|
||||
shops,
|
||||
});
|
||||
|
||||
export default getters;
|
||||
@@ -0,0 +1,12 @@
|
||||
import memberHasClass from 'common/script/libs/hasClass';
|
||||
|
||||
export function isBuffed () {
|
||||
return (member) => {
|
||||
const buffs = member.stats.buffs;
|
||||
return buffs.str || buffs.per || buffs.con || buffs.int;
|
||||
};
|
||||
}
|
||||
|
||||
export function hasClass () {
|
||||
return memberHasClass;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export function members (store) {
|
||||
return store.state.partyMembers.data;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export function market (store) {
|
||||
return store.state.shops.market;
|
||||
}
|
||||
|
||||
export function quests (store) {
|
||||
return store.state.shops.market;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import { shouldDo } from 'common/script/cron';
|
||||
|
||||
// Library / Utility function
|
||||
import { orderSingleTypeTasks } from 'client/libs/store/helpers/orderTasks.js';
|
||||
import { getActiveFilter } from 'client/libs/store/helpers/filterTasks.js';
|
||||
|
||||
import sortBy from 'lodash/sortBy';
|
||||
|
||||
// Return all the tags belonging to an user task
|
||||
export function getTagsFor (store) {
|
||||
return (task) => {
|
||||
return store.state.user.data.tags
|
||||
.filter(tag => task.tags && task.tags.indexOf(tag.id) !== -1)
|
||||
.map(tag => tag.name);
|
||||
};
|
||||
}
|
||||
|
||||
function getTaskColor (task) {
|
||||
if (task.type === 'reward' || task.byHabitica) return 'purple';
|
||||
|
||||
const value = task.value;
|
||||
|
||||
if (value < -20) {
|
||||
return 'worst';
|
||||
} else if (value < -10) {
|
||||
return 'worse';
|
||||
} else if (value < -1) {
|
||||
return 'bad';
|
||||
} else if (value < 1) {
|
||||
return 'neutral';
|
||||
} else if (value < 5) {
|
||||
return 'good';
|
||||
} else if (value < 10) {
|
||||
return 'better';
|
||||
} else {
|
||||
return 'best';
|
||||
}
|
||||
}
|
||||
|
||||
export function canDelete () {
|
||||
return (task) => {
|
||||
let isUserChallenge = Boolean(task.userId);
|
||||
let activeChallenge = isUserChallenge && task.challenge && task.challenge.id && !task.challenge.broken;
|
||||
return !activeChallenge;
|
||||
};
|
||||
}
|
||||
|
||||
export function getTaskClasses (store) {
|
||||
const userPreferences = store.state.user.data.preferences;
|
||||
|
||||
// Purpose can be one of the following strings:
|
||||
// Edit Modal: edit-modal-bg, edit-modal-text, edit-modal-icon
|
||||
// Create Modal: create-modal-bg, create-modal-text, create-modal-icon
|
||||
// Control: 'control'
|
||||
return (task, purpose, dueDate) => {
|
||||
if (!dueDate) dueDate = new Date();
|
||||
const type = task.type;
|
||||
const color = getTaskColor(task);
|
||||
|
||||
switch (purpose) {
|
||||
case 'edit-modal-bg':
|
||||
return `task-${color}-modal-bg`;
|
||||
case 'edit-modal-text':
|
||||
return `task-${color}-modal-text`;
|
||||
case 'edit-modal-icon':
|
||||
return `task-${color}-modal-icon`;
|
||||
case 'edit-modal-option-disabled':
|
||||
return `task-${color}-modal-option-disabled`;
|
||||
case 'edit-modal-habit-control-disabled':
|
||||
return `task-${color}-modal-habit-control-disabled`;
|
||||
case 'create-modal-bg':
|
||||
return 'task-purple-modal-bg';
|
||||
case 'create-modal-text':
|
||||
return 'task-purple-modal-text';
|
||||
case 'create-modal-icon':
|
||||
return 'task-purple-modal-icon';
|
||||
case 'create-modal-option-disabled':
|
||||
return 'task-purple-modal-option-disabled';
|
||||
case 'create-modal-habit-control-disabled':
|
||||
return 'task-purple-modal-habit-control-disabled';
|
||||
|
||||
case 'control':
|
||||
if (type === 'todo' || type === 'daily') {
|
||||
if (task.completed || !shouldDo(dueDate, task, userPreferences) && type === 'daily') {
|
||||
return {
|
||||
bg: 'task-disabled-daily-todo-control-bg',
|
||||
checkbox: 'task-disabled-daily-todo-control-checkbox',
|
||||
inner: 'task-disabled-daily-todo-control-inner',
|
||||
content: 'task-disabled-daily-todo-control-content',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
bg: task.group && task.group.id && !task.userId ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`,
|
||||
checkbox: `task-${color}-control-checkbox`,
|
||||
inner: `task-${color}-control-inner-daily-todo`,
|
||||
icon: `task-${color}-control-icon`,
|
||||
};
|
||||
} else if (type === 'reward') {
|
||||
return {
|
||||
bg: task.group && task.group.id && !task.userId ? 'task-reward-control-bg-noninteractive' : 'task-reward-control-bg',
|
||||
};
|
||||
} else if (type === 'habit') {
|
||||
return {
|
||||
up: task.up ?
|
||||
{ bg: task.group && task.group.id && !task.userId ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`, inner: `task-${color}-control-inner-habit`, icon: `task-${color}-control-icon`} :
|
||||
{ bg: 'task-disabled-habit-control-bg', inner: 'task-disabled-habit-control-inner', icon: `task-${color}-control-icon` },
|
||||
down: task.down ?
|
||||
{ bg: task.group && task.group.id && !task.userId ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`, inner: `task-${color}-control-inner-habit`, icon: `task-${color}-control-icon`} :
|
||||
{ bg: 'task-disabled-habit-control-bg', inner: 'task-disabled-habit-control-inner', icon: `task-${color}-control-icon` },
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 'not a valid class';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Returns all list for given task type
|
||||
export function getUnfilteredTaskList ({state}) {
|
||||
return (type) => state.tasks.data[`${type}s`];
|
||||
}
|
||||
|
||||
// Returns filtered, sorted, ordered, tag filtered, and search filtered task list
|
||||
// @TODO: sort task list based on used preferences
|
||||
export function getFilteredTaskList ({state, getters}) {
|
||||
return ({
|
||||
type,
|
||||
filterType = '',
|
||||
}) => {
|
||||
// get requested tasks
|
||||
// check if task list has been passed as override props
|
||||
// assumption: type will always be passed as param
|
||||
let requestedTasks = getters['tasks:getUnfilteredTaskList'](type);
|
||||
|
||||
let userPreferences = state.user.data.preferences;
|
||||
let taskOrderForType = state.user.data.tasksOrder[type];
|
||||
|
||||
// order tasks based on user set task order
|
||||
// Still needs unit test for this..
|
||||
if (requestedTasks.length > 0 && ['scheduled', 'due'].indexOf(filterType.label) === -1) {
|
||||
requestedTasks = orderSingleTypeTasks(requestedTasks, taskOrderForType);
|
||||
}
|
||||
|
||||
let selectedFilter = getActiveFilter(type, filterType);
|
||||
// Pass user preferences to the filter function which uses currying
|
||||
if (type === 'daily' && (filterType === 'due' || filterType === 'notDue')) {
|
||||
selectedFilter = {
|
||||
...selectedFilter,
|
||||
filterFn: selectedFilter.filterFn(userPreferences),
|
||||
};
|
||||
}
|
||||
|
||||
requestedTasks = requestedTasks.filter(selectedFilter.filterFn);
|
||||
if (selectedFilter.sort) {
|
||||
requestedTasks = sortBy(requestedTasks, selectedFilter.sort);
|
||||
}
|
||||
|
||||
return requestedTasks;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export function data (store) {
|
||||
return store.state.user.data;
|
||||
}
|
||||
|
||||
export function gems (store) {
|
||||
return store.state.user.data.balance * 4;
|
||||
}
|
||||
|
||||
export function buffs (store) {
|
||||
return (key) => store.state.user.data.stats.buffs[key];
|
||||
}
|
||||
|
||||
export function preferences (store) {
|
||||
return store.state.user.data.preferences;
|
||||
}
|
||||
|
||||
export function tasksOrder (store) {
|
||||
return (type) => store.state.user.tasksOrder[`${type}s`];
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import Store from 'client/libs/store';
|
||||
import deepFreeze from 'client/libs/deepFreeze';
|
||||
import content from 'common/script/content/index';
|
||||
import * as commonConstants from 'common/script/constants';
|
||||
import { DAY_MAPPING } from 'common/script/cron';
|
||||
import { asyncResourceFactory } from 'client/libs/asyncResource';
|
||||
import { setUpAxios } from 'client/libs/auth';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
|
||||
import actions from './actions';
|
||||
import getters from './getters';
|
||||
|
||||
const IS_TEST = process.env.NODE_ENV === 'test'; // eslint-disable-line no-process-env
|
||||
|
||||
// Load user auth parameters and determine if it's logged in
|
||||
// before trying to load data
|
||||
let isUserLoggedIn = false;
|
||||
let browserTimezoneOffset = moment().zone(); // eg, 240 - this will be converted on server as -(offset/60)
|
||||
axios.defaults.headers.common['x-client'] = 'habitica-web';
|
||||
|
||||
let AUTH_SETTINGS = localStorage.getItem('habit-mobile-settings');
|
||||
if (AUTH_SETTINGS) {
|
||||
AUTH_SETTINGS = JSON.parse(AUTH_SETTINGS);
|
||||
isUserLoggedIn = setUpAxios(AUTH_SETTINGS);
|
||||
}
|
||||
|
||||
const i18nData = window && window['habitica-i18n'];
|
||||
|
||||
let availableLanguages = [];
|
||||
let selectedLanguage = {};
|
||||
|
||||
if (i18nData) {
|
||||
availableLanguages = i18nData.availableLanguages;
|
||||
selectedLanguage = i18nData.language;
|
||||
}
|
||||
|
||||
// Export a function that generates the store and not the store directly
|
||||
// so that we can regenerate it multiple times for testing, when not testing
|
||||
// always export the same route
|
||||
|
||||
let existingStore;
|
||||
export default function () {
|
||||
if (!IS_TEST && existingStore) return existingStore;
|
||||
|
||||
existingStore = new Store({
|
||||
actions,
|
||||
getters,
|
||||
state: {
|
||||
serverAppVersion: '',
|
||||
title: 'Habitica',
|
||||
isUserLoggedIn,
|
||||
isUserLoaded: false, // Means the user and the user's tasks are ready
|
||||
isAmazonReady: false, // Whether the Amazon Payments lib can be used
|
||||
user: asyncResourceFactory(),
|
||||
credentials: isUserLoggedIn ? {
|
||||
API_ID: AUTH_SETTINGS.auth.apiId,
|
||||
API_TOKEN: AUTH_SETTINGS.auth.apiToken,
|
||||
} : {},
|
||||
// store the timezone offset in case it's different than the one in
|
||||
// user.preferences.timezoneOffset and change it after the user is synced
|
||||
// in app.vue
|
||||
browserTimezoneOffset,
|
||||
tasks: asyncResourceFactory(), // user tasks
|
||||
completedTodosStatus: 'NOT_LOADED',
|
||||
party: asyncResourceFactory(),
|
||||
partyMembers: asyncResourceFactory(),
|
||||
shops: {
|
||||
market: asyncResourceFactory(),
|
||||
quests: asyncResourceFactory(),
|
||||
seasonal: asyncResourceFactory(),
|
||||
'time-travelers': asyncResourceFactory(),
|
||||
},
|
||||
myGuilds: [],
|
||||
groupFormOptions: {
|
||||
creatingParty: false,
|
||||
groupId: '',
|
||||
},
|
||||
avatarEditorOptions: {
|
||||
editingUser: false,
|
||||
startingPage: '',
|
||||
subPage: '',
|
||||
},
|
||||
challengeOptions: {
|
||||
cloning: false,
|
||||
tasksToClone: {},
|
||||
workingChallenge: {},
|
||||
},
|
||||
editingGroup: {}, // @TODO move to local state
|
||||
// content data, frozen to prevent Vue from modifying it since it's static and never changes
|
||||
// @TODO apply freezing to the entire codebase (the server) and not only to the client side?
|
||||
// NOTE this takes about 10-15ms on a fast computer
|
||||
content: deepFreeze(content),
|
||||
constants: deepFreeze({...commonConstants, DAY_MAPPING}),
|
||||
i18n: deepFreeze({
|
||||
availableLanguages,
|
||||
selectedLanguage,
|
||||
}),
|
||||
hideHeader: false,
|
||||
memberModalOptions: {
|
||||
viewingMembers: [],
|
||||
groupId: '',
|
||||
challengeId: '',
|
||||
group: {},
|
||||
},
|
||||
openedItemRows: [],
|
||||
spellOptions: {
|
||||
castingSpell: false,
|
||||
spellDrawOpen: true,
|
||||
},
|
||||
profileOptions: {
|
||||
startingPage: '',
|
||||
},
|
||||
gemModalOptions: {
|
||||
startingPage: '',
|
||||
},
|
||||
rageModalOptions: {
|
||||
npc: '',
|
||||
},
|
||||
profileUser: {},
|
||||
upgradingGroup: {},
|
||||
notificationStore: [],
|
||||
modalStack: [],
|
||||
equipmentDrawerOpen: true,
|
||||
groupPlans: [],
|
||||
isRunningYesterdailies: false,
|
||||
},
|
||||
});
|
||||
|
||||
return existingStore;
|
||||
}
|
||||
Reference in New Issue
Block a user