mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
fixes and start client
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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') {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export function members (store) {
|
||||
export function members (store) { // eslint-disable-line import/prefer-default-export
|
||||
return store.state.partyMembers.data;
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
mocha: true,
|
||||
},
|
||||
};
|
||||
module.exports = require('../../../../test/.eslintrc.js');
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -45,6 +45,7 @@ export async function recoverCron (status, locals) {
|
||||
}
|
||||
} else {
|
||||
locals.user = reloadedUser;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user