fixes and start client

This commit is contained in:
Matteo Pagliazzi
2019-10-10 22:15:58 +02:00
parent 8bae0223bb
commit ce4729f069
23 changed files with 64 additions and 58 deletions

View File

@@ -72,7 +72,7 @@
"npm": "^6"
},
"scripts": {
"lint": "eslint --ext .js --fix ./website/server",
"lint": "eslint --ext .js --fix ./website/common",
"test": "npm run lint && gulp test && gulp apidoc",
"test:build": "gulp test:prepare:build",
"test:api-v3": "gulp test:api-v3",

View File

@@ -9,18 +9,9 @@ module.exports = {
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'import/no-unresolved': 'off',
},
parserOptions: {
parser: 'babel-eslint',
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
],
env: {
mocha: true,
},
},
],
};

View File

@@ -247,7 +247,7 @@ export default {
const min = 1;
const randomNumber = Math.random() * (numberOfTips - min) + min;
const tipNumber = Math.floor(randomNumber);
this.currentTipNumber = tipNumber; // eslint-disable-line vue/no-side-effects-in-computed-properties
this.currentTipNumber = tipNumber; // eslint-disable-line vue/no-side-effects-in-computed-properties, max-len
return this.$t(`tip${tipNumber}`);
},
@@ -283,7 +283,8 @@ export default {
this.$refs.sound.load();
});
// @TODO: I'm not sure these should be at the app level. Can we move these back into shop/inventory or maybe they need a lateral move?
// @TODO: I'm not sure these should be at the app level.
// Can we move these back into shop/inventory or maybe they need a lateral move?
this.$root.$on('buyModal::showItem', item => {
this.selectedItemToBuy = item;
this.$root.$emit('bv::show::modal', 'buy-modal');
@@ -398,7 +399,8 @@ export default {
// if (isApiCall && !serverAppVersionState) {
// this.$store.state.serverAppVersion = serverAppVersion;
// } else if (isApiCall && serverAppVersionState !== serverAppVersion) {
// if (document.activeElement.tagName !== 'INPUT' || confirm(this.$t('habiticaHasUpdated'))) {
// if (document.activeElement.tagName !== 'INPUT'
// || confirm(this.$t('habiticaHasUpdated'))) {
// location.reload(true);
// }
// }
@@ -537,12 +539,13 @@ export default {
const modalCount = {};
const prevAndCurrent = 2;
for (const index in modalStack) {
const current = modalStack[index];
for (const current of modalStack) {
if (!modalCount[current.modalId]) modalCount[current.modalId] = 0;
modalCount[current.modalId] += 1;
if (modalCount[current.modalId] > prevAndCurrent && modalsThatCanShowTwice.indexOf(current.modalId) === -1) {
if (
modalCount[current.modalId] > prevAndCurrent
&& modalsThatCanShowTwice.indexOf(current.modalId) === -1
) {
this.$store.state.modalStack = [];
return false;
}
@@ -550,7 +553,10 @@ export default {
if (!current.prev) continue; // eslint-disable-line
if (!modalCount[current.prev]) modalCount[current.prev] = 0;
modalCount[current.prev] += 1;
if (modalCount[current.prev] > prevAndCurrent && modalsThatCanShowTwice.indexOf(current.prev) === -1) {
if (
modalCount[current.prev] > prevAndCurrent
&& modalsThatCanShowTwice.indexOf(current.prev) === -1
) {
this.$store.state.modalStack = [];
return false;
}

View File

@@ -1,4 +1,5 @@
import Vue from 'vue';
import BootstrapVue from 'bootstrap-vue';
import AppComponent from './app';
import {
setup as setupAnalytics,
@@ -9,9 +10,7 @@ import getStore from './store';
import StoreModule from './libs/store';
import './filters/registerGlobals';
import i18n from './libs/i18n';
import 'smartbanner.js/dist/smartbanner.js';
import BootstrapVue from 'bootstrap-vue';
import 'smartbanner.js/dist/smartbanner';
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
@@ -34,7 +33,7 @@ setUpLogging();
setupAnalytics(); // just create queues for analytics, no scripts loaded at this time
const store = getStore();
new Vue({
export default new Vue({
el: '#app',
router,
store,

View File

@@ -29,7 +29,8 @@ const Logout = () => import(/* webpackChunkName: "auth" */'@/components/auth/log
// User Pages
// const StatsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/stats');
// const AchievementsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/achievements');
// const AchievementsPage =
// () => import(/* webpackChunkName: "user" */'./components/userMenu/achievements');
const ProfilePage = () => import(/* webpackChunkName: "user" */'@/components/userMenu/profilePage');
// Settings
@@ -413,7 +414,8 @@ router.beforeEach((to, from, next) => {
startingPage,
path: to.path,
});
return;
return null;
}
if ((to.name === 'stats' || to.name === 'achievements' || to.name === 'profile') && from.name !== null) {
@@ -421,7 +423,7 @@ router.beforeEach((to, from, next) => {
startingPage: to.name,
path: to.path,
});
return;
return null;
}
if (from.name === 'userProfile' || from.name === 'userProfilePage' || from.name === 'stats' || from.name === 'achievements' || from.name === 'profile') {

View File

@@ -76,7 +76,9 @@ export async function exportChallengeCsv (store, payload) {
export async function updateChallenge (store, payload) {
const challengeDataToSend = omit(payload.challenge, ['tasks', 'habits', 'todos', 'rewards', 'group']);
if (challengeDataToSend.leader && challengeDataToSend.leader._id) challengeDataToSend.leader = challengeDataToSend.leader._id;
if (challengeDataToSend.leader && challengeDataToSend.leader._id) {
challengeDataToSend.leader = challengeDataToSend.leader._id;
}
const response = await axios.put(`/api/v4/challenges/${payload.challenge._id}`, challengeDataToSend);

View File

@@ -60,7 +60,7 @@ export async function join (store, payload) {
response = await axios.post(`/api/v4/groups/${groupId}/join`);
} catch (err) {
alert(err.response.data.message);
return;
return null;
}
if (type === 'guild') {
@@ -120,7 +120,9 @@ export async function create (store, payload) {
export async function update (store, payload) {
// Remove populated fields
const groupDetailsToSend = omit(payload.group, ['chat', 'challenges', 'members', 'invites']);
if (groupDetailsToSend.leader && groupDetailsToSend.leader._id) groupDetailsToSend.leader = groupDetailsToSend.leader._id;
if (groupDetailsToSend.leader && groupDetailsToSend.leader._id) {
groupDetailsToSend.leader = groupDetailsToSend.leader._id;
}
const response = await axios.put(`/api/v4/groups/${payload.group.id}`, groupDetailsToSend);

View File

@@ -4,7 +4,7 @@ import * as Analytics from '@/libs/analytics';
// export async function initQuest (store) {
// }
export async function sendAction (store, payload) {
export async function sendAction (store, payload) { // eslint-disable-line import/prefer-default-export, max-len
// @TODO: Maybe move this to server
let partyData = {};
if (store.state.party && store.state.party.data) {

View File

@@ -11,7 +11,8 @@ import releaseBothOp from '@/../../common/script/ops/releaseBoth';
import { getDropClass } from '@/libs/notifications';
// @TODO: Purchase means gems and buy means gold. That wording is misused below, but we should also change
// @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) {
@@ -63,7 +64,9 @@ async function buyArmoire (store, params) {
}
if (item.type === 'food') {
if (!store.state.user.data.items.food[item.dropKey]) store.state.user.data.items.food[item.dropKey] = 0;
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;
}
@@ -136,9 +139,8 @@ 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 'armoire':
return buyArmoire(store, params);
case 'fortify': {
const rerollResult = rerollOp(store.state.user.data, store.state.tasks.data);

View File

@@ -7,5 +7,6 @@ export function add (store, payload) {
}
export function remove (store, payload) {
store.state.notificationStore = store.state.notificationStore.filter(notification => notification.uuid !== payload.uuid);
store.state.notificationStore = store.state.notificationStore
.filter(notification => notification.uuid !== payload.uuid);
}

View File

@@ -22,7 +22,7 @@ export function fetch (store, options = {}) { // eslint-disable-line no-shadow
export async function set (store, changes) {
const user = store.state.user.data;
for (const key in changes) {
for (const key of Object.keys(changes)) {
if (key === 'tags') {
// Keep challenge and group tags
const oldTags = user.tags.filter(t => t.group);
@@ -37,7 +37,7 @@ export async function set (store, changes) {
const tagsIndexesToRemove = [];
task.tags.forEach((tagId, tagIndex) => {
if (user.tags.find(tag => tag.id === tagId)) return; // eslint-disable-line max-nested-callbacks
if (user.tags.find(tag => tag.id === tagId)) return;
tagsIndexesToRemove.push(tagIndex);
});

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
export async function getWorldState () {
export async function getWorldState () { // eslint-disable-line import/prefer-default-export
const url = '/api/v4/world-state';
const response = await axios.get(url);
return response.data.data;

View File

@@ -1,3 +1,3 @@
export function members (store) {
export function members (store) { // eslint-disable-line import/prefer-default-export
return store.state.partyMembers.data;
}

View File

@@ -2,8 +2,8 @@ import sortBy from 'lodash/sortBy';
import { shouldDo } from '@/../../common/script/cron';
// Library / Utility function
import { orderSingleTypeTasks } from '@/libs/store/helpers/orderTasks.js';
import { getActiveFilter } from '@/libs/store/helpers/filterTasks.js';
import { orderSingleTypeTasks } from '@/libs/store/helpers/orderTasks';
import { getActiveFilter } from '@/libs/store/helpers/filterTasks';
// Return all the tags belonging to an user task
@@ -37,7 +37,8 @@ function getTaskColor (task) {
export function canDelete () {
return task => {
const isUserChallenge = Boolean(task.userId);
const activeChallenge = isUserChallenge && task.challenge && task.challenge.id && !task.challenge.broken;
const activeChallenge = isUserChallenge
&& task.challenge && task.challenge.id && !task.challenge.broken;
return !activeChallenge;
};
}
@@ -50,7 +51,7 @@ export function getTaskClasses (store) {
// Create Modal: create-modal-bg, create-modal-text, create-modal-icon
// Control: 'control'
return (task, purpose, dueDate) => {
if (!dueDate) dueDate = new Date();
if (!dueDate) dueDate = new Date(); // eslint-disable-line no-param-reassign
const { type } = task;
const color = getTaskColor(task);
@@ -78,7 +79,7 @@ export function getTaskClasses (store) {
case 'control':
if (type === 'todo' || type === 'daily') {
if (task.completed || !shouldDo(dueDate, task, userPreferences) && 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',
@@ -107,7 +108,7 @@ export function getTaskClasses (store) {
: { bg: 'task-disabled-habit-control-bg', inner: 'task-disabled-habit-control-inner', icon: `task-${color}-control-icon` },
};
}
break;
return null;
default:
return 'not a valid class';
}

View File

@@ -16,7 +16,10 @@ const IS_TEST = process.env.NODE_ENV === 'test'; // eslint-disable-line no-proce
// Load user auth parameters and determine if it's logged in
// before trying to load data
let isUserLoggedIn = false;
const browserTimezoneOffset = moment().zone(); // eg, 240 - this will be converted on server as -(offset/60)
// eg, 240 - this will be converted on server as -(offset/60)
const browserTimezoneOffset = moment().zone();
axios.defaults.headers.common['x-client'] = 'habitica-web';
let AUTH_SETTINGS = localStorage.getItem('habit-mobile-settings');

View File

@@ -1,5 +1 @@
module.exports = {
env: {
mocha: true,
},
};
module.exports = require('../../../../test/.eslintrc.js');

View File

@@ -128,7 +128,7 @@ export function shouldDo (day, dailyTask, options = {}) {
const daysOfTheWeek = [];
if (dailyTask.repeat) {
for (const [repeatDay, active] of Object.entries(dailyTask.repeat)) {
if (!Number.isFinite(DAY_MAPPING_STRING_TO_NUMBER[repeatDay])) continue; // eslint-disable-line no-continue, max-len
if (!Number.isFinite(parseInt(DAY_MAPPING_STRING_TO_NUMBER[repeatDay], 10))) continue; // eslint-disable-line no-continue, max-len
if (active) daysOfTheWeek.push(parseInt(DAY_MAPPING_STRING_TO_NUMBER[repeatDay], 10));
}
}

View File

@@ -27,7 +27,7 @@ export class BuyGemOperation extends AbstractGoldItemOperation { // eslint-disab
extractAndValidateParams (user, req) {
this.key = get(req, 'params.key');
const { key } = this.key;
const { key } = this;
if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
let { convCap } = planGemLimits;

View File

@@ -34,7 +34,7 @@ export class BuyMarketGearOperation extends AbstractGoldItemOperation { // eslin
extractAndValidateParams (user, req) {
this.key = get(req, 'params.key');
const { key } = this.key;
const { key } = this;
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
const item = content.gear.flat[key];

View File

@@ -28,7 +28,7 @@ export class BuyQuestWithGemOperation extends AbstractGemItemOperation { // esli
extractAndValidateParams (user, req) {
this.key = get(req, 'params.key');
const { key } = this.key;
const { key } = this;
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
const item = content.quests[key];

View File

@@ -608,7 +608,7 @@ api.exportChallengeCsv = {
}
while (task.userId !== lastUserId) {
index += 1;
lastUserId = [resArray[index]]; // resArray[index][0] is an user id
[lastUserId] = resArray[index]; // resArray[index][0] is an user id
}
const streak = task.streak || 0;

View File

@@ -45,6 +45,7 @@ export async function recoverCron (status, locals) {
}
} else {
locals.user = reloadedUser;
return null;
}
}

View File

@@ -136,7 +136,7 @@ api.cancelSubscription = async function cancelSubscription (options, stripeInc)
if (customer && (customer.subscription || customer.subscriptions)) {
let { subscription } = customer;
if (!subscription && customer.subscriptions) {
subscription = [customer.subscriptions.data];
[subscription] = customer.subscriptions.data;
}
await stripeApi.customers.del(customerId);