lint common

This commit is contained in:
Matteo Pagliazzi
2019-10-09 20:08:36 +02:00
parent 0c27fb24a5
commit e0e9811ab6
330 changed files with 6885 additions and 7668 deletions

6
package-lock.json generated
View File

@@ -4476,9 +4476,9 @@
}
},
"eslint-config-habitrpg": {
"version": "6.0.7",
"resolved": "https://registry.npmjs.org/eslint-config-habitrpg/-/eslint-config-habitrpg-6.0.7.tgz",
"integrity": "sha512-hda2IKsfwE/94CjLtPI3Cgsq0capQCFKCiqPPNM7foeO/E6cZpXCSvMHdGt5TXy66DQxF5h+kz4xcheHdcaRcA==",
"version": "6.0.8",
"resolved": "https://registry.npmjs.org/eslint-config-habitrpg/-/eslint-config-habitrpg-6.0.8.tgz",
"integrity": "sha512-jQ62H3+Gkie4CK8uFfV37SX+yNs6yu+SHP27hIYIlnZ21HCaQnabEQfhrYzbpQUn9fNd2y1gUNqGOIG8ph84vg==",
"dev": true,
"requires": {
"eslint": "^6.5.1",

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",
@@ -103,7 +103,7 @@
"chai-as-promised": "^7.1.1",
"chalk": "^2.4.1",
"eslint": "^6.5.1",
"eslint-config-habitrpg": "^6.0.7",
"eslint-config-habitrpg": "^6.0.8",
"eslint-plugin-mocha": "^5.0.0",
"expect.js": "^0.3.1",
"istanbul": "^1.1.0-alpha.1",

View File

@@ -1,47 +0,0 @@
/* global env:true, rm:true, mkdir:true, cp:true */
// https://github.com/shelljs/shelljs
require('shelljs/global');
const path = require('path');
const config = require('./config');
const ora = require('ora');
const webpack = require('webpack');
const webpackConfig = require('./webpack.prod.conf');
module.exports = function webpackProductionBuild (callback) {
env.NODE_ENV = 'production';
console.log( // eslint-disable-line no-console
' Tip:\n' +
' Built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
);
const spinner = ora('building for production...');
spinner.start();
const assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory);
rm('-rf', assetsPath);
mkdir('-p', assetsPath);
cp('-R', config.build.staticAssetsDirectory, assetsPath);
webpack(webpackConfig, (err, stats) => {
spinner.stop();
const output = `${stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false,
})}\n`;
if (callback) {
return err ? callback(err) : callback(null, output);
} else {
if (err) throw err;
process.stdout.write(output);
}
});
};

View File

@@ -1,6 +0,0 @@
const merge = require('webpack-merge');
const prodEnv = require('./prod.env');
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
});

View File

@@ -1,81 +0,0 @@
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path');
const staticAssetsDirectory = './website/static/.'; // The folder where static files (not processed) live
const prodEnv = require('./prod.env');
const devEnv = require('./dev.env');
const nconf = require('nconf');
const setupNconf = require('../../website/server/libs/setupNconf');
let configFile = path.join(path.resolve(__dirname, '../../config.json'));
setupNconf(configFile);
const DEV_BASE_URL = nconf.get('BASE_URL');
module.exports = {
build: {
env: prodEnv,
index: path.resolve(__dirname, '../../dist-client/index.html'),
assetsRoot: path.resolve(__dirname, '../../dist-client'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
staticAssetsDirectory,
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run client:build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report, // eslint-disable-line no-process-env
},
dev: {
env: devEnv,
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
staticAssetsDirectory,
proxyTable: {
// proxy all requests to the server at IP:PORT as specified in the top-level config
'/api/v3': {
target: DEV_BASE_URL,
changeOrigin: true,
},
'/api/v4': {
target: DEV_BASE_URL,
changeOrigin: true,
},
'/stripe': {
target: DEV_BASE_URL,
changeOrigin: true,
},
'/amazon': {
target: DEV_BASE_URL,
changeOrigin: true,
},
'/paypal': {
target: DEV_BASE_URL,
changeOrigin: true,
},
'/logout-server': {
target: DEV_BASE_URL,
changeOrigin: true,
},
'/export': {
target: DEV_BASE_URL,
changeOrigin: true,
},
},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false,
},
};

View File

@@ -1,45 +0,0 @@
const nconf = require('nconf');
const { join, resolve } = require('path');
const setupNconf = require('../../website/server/libs/setupNconf');
const PATH_TO_CONFIG = join(resolve(__dirname, '../../config.json'));
let configFile = PATH_TO_CONFIG;
setupNconf(configFile);
// @TODO: Check if we can import from client. Items like admin emails can be imported
// and that should be prefered
// To avoid stringifying more data then we need,
// items from `env` used on the client will have to be specified in this array
// @TODO: Do we need? const CLIENT_VARS = ['language', 'isStaticPage', 'availableLanguages', 'translations',
// 'FACEBOOK_KEY', 'GOOGLE_CLIENT_ID', 'NODE_ENV', 'BASE_URL', 'GA_ID',
// 'AMAZON_PAYMENTS', 'STRIPE_PUB_KEY', 'AMPLITUDE_KEY',
// 'worldDmg', 'mods', 'IS_MOBILE'];
const AMAZON_SELLER_ID = nconf.get('AMAZON_PAYMENTS_SELLER_ID');
const AMAZON_CLIENT_ID = nconf.get('AMAZON_PAYMENTS_CLIENT_ID');
const AMAZON_MODE = nconf.get('AMAZON_PAYMENTS_MODE');
let env = {
NODE_ENV: '"production"',
// clientVars: CLIENT_VARS,
AMAZON_PAYMENTS: {
SELLER_ID: `"${AMAZON_SELLER_ID}"`,
CLIENT_ID: `"${AMAZON_CLIENT_ID}"`,
MODE: `"${AMAZON_MODE}"`,
},
EMAILS: {
COMMUNITY_MANAGER_EMAIL: `"${nconf.get('EMAILS_COMMUNITY_MANAGER_EMAIL')}"`,
TECH_ASSISTANCE_EMAIL: `"${nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL')}"`,
PRESS_ENQUIRY_EMAIL: `"${nconf.get('EMAILS_PRESS_ENQUIRY_EMAIL')}"`,
},
};
'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_KEY GOOGLE_CLIENT_ID AMPLITUDE_KEY LOGGLY_CLIENT_TOKEN'
.split(' ')
.forEach(key => {
env[key] = `"${nconf.get(key)}"`;
});
module.exports = env;

View File

@@ -1,6 +0,0 @@
const merge = require('webpack-merge');
const devEnv = require('./dev.env');
module.exports = merge(devEnv, {
NODE_ENV: '"test"',
});

View File

@@ -1,10 +0,0 @@
/* global window:true */
require('eventsource-polyfill');
const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true&overlay=false');
hotClient.subscribe(event => {
if (event.action === 'reload') {
window.location.reload();
}
});

View File

@@ -1,72 +0,0 @@
/* eslint-disable no-process-env, no-console */
const path = require('path');
const express = require('express');
const webpack = require('webpack');
const config = require('./config');
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV);
}
const proxyMiddleware = require('http-proxy-middleware');
const webpackConfig = process.env.NODE_ENV === 'test' ?
require('./webpack.prod.conf') :
require('./webpack.dev.conf');
// default port where dev server listens for incoming traffic
const port = process.env.PORT || config.dev.port;
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
const proxyTable = config.dev.proxyTable;
const app = express();
const compiler = webpack(webpackConfig);
const devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true,
chunks: false,
},
});
const hotMiddleware = require('webpack-hot-middleware')(compiler);
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', (compilation) => {
compilation.plugin('html-webpack-plugin-after-emit', (data, cb) => {
hotMiddleware.publish({ action: 'reload' });
cb();
});
});
// proxy api requests
Object.keys(proxyTable).forEach((context) => {
let options = proxyTable[context];
if (typeof options === 'string') {
options = { target: options };
}
app.use(proxyMiddleware(options.filter || context, options));
});
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')());
// serve webpack bundle output
app.use(devMiddleware);
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware);
// serve pure static assets
const staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory);
app.use(staticPath, express.static(config.dev.staticAssetsDirectory));
module.exports = app.listen(port, (err) => {
if (err) {
console.log(err);
return;
}
console.log(`Listening at http://localhost:${port}\n`);
});

View File

@@ -1,66 +0,0 @@
/* eslint-disable no-process-env, no-console */
const path = require('path');
const config = require('./config');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
exports.assetsPath = (_path) => {
const assetsSubDirectory = process.env.NODE_ENV === 'production' ?
config.build.assetsSubDirectory :
config.dev.assetsSubDirectory;
return path.posix.join(assetsSubDirectory, _path);
};
exports.cssLoaders = function cssLoaders (options) {
options = options || {};
// generate loader string to be used with extract text plugin
function generateLoaders (loaders) {
let sourceLoader = loaders.map((loader) => {
let extraParamChar;
if (/\?/.test(loader)) {
loader = loader.replace(/\?/, '-loader?');
extraParamChar = '&';
} else {
loader = `${loader}-loader`;
extraParamChar = '?';
}
return loader + (options.sourceMap ? `${extraParamChar}sourceMap` : '');
}).join('!');
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: sourceLoader,
fallback: 'vue-style-loader',
});
} else {
return ['vue-style-loader', sourceLoader].join('!');
}
}
// http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
return {
css: generateLoaders(['css']),
postcss: generateLoaders(['css']),
less: generateLoaders(['css', 'less']),
sass: generateLoaders(['css', 'sass?indentedSyntax']),
scss: generateLoaders(['css', 'sass']),
stylus: generateLoaders(['css', 'stylus']),
styl: generateLoaders(['css', 'stylus']),
};
};
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = (options) => {
const output = [];
const loaders = exports.cssLoaders(options);
for (let extension in loaders) {
const loader = loaders[extension];
output.push({
test: new RegExp(`\\.${extension}$`),
loader,
});
}
return output;
};

View File

@@ -1,154 +0,0 @@
/* eslint-disable no-process-env, no-console */
const path = require('path');
const config = require('./config');
const utils = require('./utils');
const webpack = require('webpack');
const projectRoot = path.resolve(__dirname, '../');
const autoprefixer = require('autoprefixer');
const postcssEasyImport = require('postcss-easy-import');
const IS_PROD = process.env.NODE_ENV === 'production';
const baseConfig = {
entry: {
app: ['babel-polyfill', './website/client/main.js'],
},
output: {
path: config.build.assetsRoot,
publicPath: IS_PROD ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
filename: '[name].js',
devtoolModuleFilenameTemplate (info) {
// Fix source maps, code from
// https://github.com/Darkside73/bbsmile.com.ua/commit/3596d3c42ef91b69d8380359c3e8908edc08acdb
let filename = info.resourcePath;
if (info.resource.match(/\.vue$/) && !info.allLoaders.match(/type=script/)) {
filename = 'generated';
}
return filename;
},
},
resolve: {
extensions: ['*', '.js', '.vue', '.json'],
modules: [
path.join(projectRoot, 'website'),
path.join(projectRoot, 'test/client/unit'),
path.join(projectRoot, 'node_modules'),
],
alias: {
website: path.resolve(projectRoot, 'website'),
common: path.resolve(projectRoot, 'website/common'),
client: path.resolve(projectRoot, 'website/client'),
assets: path.resolve(projectRoot, 'website/client/assets'),
components: path.resolve(projectRoot, 'website/client/components'),
},
},
plugins: [
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(NOT_EXISTING)$/),
],
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: utils.cssLoaders({
sourceMap: IS_PROD ?
config.build.productionSourceMap :
config.dev.cssSourceMap,
extract: IS_PROD,
}),
postcss: [
autoprefixer({
overrideBrowserslist: ['last 2 versions'],
}),
postcssEasyImport(),
],
},
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [
path.join(projectRoot, 'test'),
path.join(projectRoot, 'website'),
path.join(projectRoot, 'node_modules', 'bootstrap-vue'),
],
options: {
cacheDirectory: true,
},
},
{
test: /\.(png|jpe?g|gif)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('images/[name].[hash:7].[ext]'),
},
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]'),
},
},
{
test: /\.svg$/,
use: [
{ loader: 'svg-inline-loader' },
{
loader: 'svgo-loader',
options: {
plugins: [
{removeViewBox: false},
{convertPathData: {noSpaceAfterFlags: false}},
],
},
},
],
exclude: [path.resolve(projectRoot, 'website/client/assets/svg/for-css')],
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
options: {
limit: 10000,
name: utils.assetsPath('svg/[name].[hash:7].[ext]'),
},
},
{
loader: 'svgo-loader',
options: {
plugins: [
{removeViewBox: false},
{convertPathData: {noSpaceAfterFlags: false}},
],
},
},
],
include: [path.resolve(projectRoot, 'website/client/assets/svg/for-css')],
},
],
},
};
if (!IS_PROD) {
const eslintFriendlyFormatter = require('eslint-friendly-formatter'); // eslint-disable-line global-require
baseConfig.module.rules.unshift({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: projectRoot,
options: {
formatter: eslintFriendlyFormatter,
emitWarning: true,
},
exclude: /node_modules/,
});
}
module.exports = baseConfig;

View File

@@ -1,32 +0,0 @@
const config = require('./config');
const webpack = require('webpack');
const merge = require('webpack-merge');
const utils = require('./utils');
const baseWebpackConfig = require('./webpack.base.conf');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach((name) => {
baseWebpackConfig.entry[name] = baseWebpackConfig.entry[name].concat('./webpack/dev-client');
});
module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }),
},
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env,
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: './website/client/index.html',
inject: true,
}),
],
});

View File

@@ -1,101 +0,0 @@
/* eslint-disable no-process-env, no-console */
const path = require('path');
const config = require('./config');
const utils = require('./utils');
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const env = process.env.NODE_ENV === 'test' ?
require('./config/test.env') :
config.build.env;
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }),
},
devtool: config.build.productionSourceMap ? '#source-map' : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
},
plugins: [
// http://vuejs.github.io/vue-loader/workflow/production.html
new webpack.DefinePlugin({
'process.env': env,
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
},
sourceMap: true,
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'test' ?
'index.html' :
config.build.index,
template: './website/client/index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency',
}),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (scriptModule) {
// any required modules inside node_modules are extracted to vendor
return (
scriptModule.resource &&
/\.js$/.test(scriptModule.resource) &&
scriptModule.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
);
},
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor'],
}),
],
});
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin'); // eslint-disable-line global-require
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(`\\.(${config.build.productionGzipExtensions.join('|')})$`),
threshold: 10240,
minRatio: 0.8,
})
);
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; // eslint-disable-line global-require
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = webpackConfig;

View File

@@ -1,24 +0,0 @@
// This is the webpack config used for unit tests.
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.conf');
const utils = require('./utils');
const webpack = require('webpack');
const testEnv = require('./config/test.env');
const webpackConfig = merge(baseConfig, {
// use inline sourcemap for karma-sourcemap-loader
module: {
rules: utils.styleLoaders(),
},
devtool: '#inline-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': testEnv,
}),
],
});
// no need for app entry during tests
delete webpackConfig.entry;
module.exports = webpackConfig;

View File

@@ -1,27 +1,26 @@
module.exports = {
root: true,
env: {
node: true
node: true,
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
extends: [
'habitrpg/lib/vue',
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
},
parserOptions: {
parser: 'babel-eslint'
parser: 'babel-eslint',
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)'
'**/__tests__/*.{j,t}s?(x)',
],
env: {
mocha: true
}
}
]
}
mocha: true,
},
},
],
};

View File

@@ -1,5 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
'@vue/cli-plugin-babel/preset',
],
};

View File

@@ -1,5 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}
autoprefixer: {},
},
};

View File

@@ -201,8 +201,7 @@ import bannedAccountModal from '@/components/bannedAccountModal';
const COMMUNITY_MANAGER_EMAIL = process.env.EMAILS_COMMUNITY_MANAGER_EMAIL; // eslint-disable-line
export default {
mixins: [notifications, spellsMixin],
name: 'app',
name: 'App',
components: {
AppMenu,
AppHeader,
@@ -217,6 +216,7 @@ export default {
subCancelModalConfirm,
subCanceledModal,
},
mixins: [notifications, spellsMixin],
data () {
return {
icons: Object.freeze({
@@ -235,9 +235,9 @@ export default {
},
computed: {
...mapState(['isUserLoggedIn', 'browserTimezoneOffset', 'isUserLoaded']),
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isStaticPage () {
return this.$route.meta.requiresLogin === false ? true : false;
return this.$route.meta.requiresLogin === false;
},
castingSpell () {
return this.$store.state.spellOptions.castingSpell;
@@ -256,14 +256,14 @@ export default {
},
},
created () {
this.$root.$on('playSound', (sound) => {
let theme = this.user.preferences.sound;
this.$root.$on('playSound', sound => {
const theme = this.user.preferences.sound;
if (!theme || theme === 'off') {
return;
}
let file = `/static/audio/${theme}/${sound}`;
const file = `/static/audio/${theme}/${sound}`;
if (this.audioSuffix === null) {
this.audioSource = document.createElement('source');
@@ -284,12 +284,12 @@ export default {
});
// @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.$root.$on('buyModal::showItem', item => {
this.selectedItemToBuy = item;
this.$root.$emit('bv::show::modal', 'buy-modal');
});
this.$root.$on('selectMembersModal::showItem', (item) => {
this.$root.$on('selectMembersModal::showItem', item => {
this.selectedSpellToBuy = item;
this.$root.$emit('bv::show::modal', 'select-member-modal');
});
@@ -301,18 +301,18 @@ export default {
});
// Set up Error interceptors
axios.interceptors.response.use((response) => {
axios.interceptors.response.use(response => {
if (this.user && response.data && response.data.notifications) {
this.$set(this.user, 'notifications', response.data.notifications);
}
return response;
}, (error) => {
}, error => {
if (error.response.status >= 400) {
this.checkForBannedUser(error);
// Don't show errors from getting user details. These users have delete their account,
// but their chat message still exists.
let configExists = Boolean(error.response) && Boolean(error.response.config);
const configExists = Boolean(error.response) && Boolean(error.response.config);
if (configExists && error.response.config.method === 'get' && error.response.config.url.indexOf('/api/v4/members/') !== -1) {
// @TODO: We resolve the promise because we need our caching to cache this user as tried
// Chat paging should help this, but maybe we can also find another solution..
@@ -333,11 +333,11 @@ export default {
let snackbarTimeout = false;
if (error.response.status === 502) snackbarTimeout = true;
let errorsToShow = [];
const errorsToShow = [];
// show only the first error for each param
let paramErrorsFound = {};
const paramErrorsFound = {};
if (errorData.errors) {
for (let e of errorData.errors) {
for (const e of errorData.errors) {
if (!paramErrorsFound[e.param]) {
errorsToShow.push(e.message);
paramErrorsFound[e.param] = true;
@@ -362,11 +362,11 @@ export default {
return Promise.reject(error);
});
axios.interceptors.response.use((response) => {
axios.interceptors.response.use(response => {
// Verify that the user was not updated from another browser/app/client
// If it was, sync
const url = response.config.url;
const method = response.config.method;
const { url } = response.config;
const { method } = response.config;
const isApiCall = url.indexOf('api/v4') !== -1;
const userV = response.data && response.data.userV;
@@ -386,8 +386,8 @@ export default {
// Something has changed on the user object that was not tracked here, sync the user
if (userV - oldUserV > 1 && !isCron && !isChatSeen && !isUserSync && !isTasksSync) {
Promise.all([
this.$store.dispatch('user:fetch', {forceLoad: true}),
this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
this.$store.dispatch('user:fetch', { forceLoad: true }),
this.$store.dispatch('tasks:fetchUserTasks', { forceLoad: true }),
]);
}
}
@@ -407,7 +407,7 @@ export default {
});
// Setup listener for title
this.$store.watch(state => state.title, (title) => {
this.$store.watch(state => state.title, title => {
document.title = title;
});
this.$nextTick(() => {
@@ -446,7 +446,7 @@ export default {
// Load external scripts after the app has been rendered
setupPayments();
});
}).catch((err) => {
}).catch(err => {
console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console
});
} else {
@@ -491,17 +491,17 @@ export default {
// Manage modals
this.$root.$on('bv::show::modal', (modalId, data = {}) => {
if (data.fromRoot) return;
const modalStack = this.$store.state.modalStack;
const { modalStack } = this.$store.state;
this.trackGemPurchase(modalId, data);
// Add new modal to the stack
const prev = modalStack[modalStack.length - 1];
const prevId = prev ? prev.modalId : undefined;
modalStack.push({modalId, prev: prevId});
modalStack.push({ modalId, prev: prevId });
});
this.$root.$on('bv::modal::hidden', (bvEvent) => {
this.$root.$on('bv::modal::hidden', bvEvent => {
let modalId = bvEvent.target && bvEvent.target.id;
// sometimes the target isn't passed to the hidden event, fallback is the vueTarget
@@ -513,7 +513,7 @@ export default {
return;
}
const modalStack = this.$store.state.modalStack;
const { modalStack } = this.$store.state;
const modalOnTop = modalStack[modalStack.length - 1];
@@ -529,7 +529,7 @@ export default {
// Get previous modal
const modalBefore = modalOnTop ? modalOnTop.prev : undefined;
if (modalBefore) this.$root.$emit('bv::show::modal', modalBefore, {fromRoot: true});
if (modalBefore) this.$root.$emit('bv::show::modal', modalBefore, { fromRoot: true });
});
},
validStack (modalStack) {
@@ -537,7 +537,7 @@ export default {
const modalCount = {};
const prevAndCurrent = 2;
for (let index in modalStack) {
for (const index in modalStack) {
const current = modalStack[index];
if (!modalCount[current.modalId]) modalCount[current.modalId] = 0;
@@ -574,11 +574,9 @@ export default {
this.selectedItemToBuy = item;
},
genericPurchase (item) {
if (!item)
return false;
if (!item) return false;
if (['card', 'debuffPotion'].includes(item.purchaseType))
return false;
if (['card', 'debuffPotion'].includes(item.purchaseType)) return false;
return true;
},
@@ -609,7 +607,7 @@ export default {
this.selectedSpellToBuy = null;
if (this.user.party._id) {
this.$store.dispatch('party:getMembers', {forceLoad: true});
this.$store.dispatch('party:getMembers', { forceLoad: true });
}
this.$root.$emit('bv::hide::modal', 'select-member-modal');

View File

@@ -16,10 +16,9 @@ export default {
...mapState(['isUserLoggedIn']),
contactUsLink () {
if (this.isUserLoggedIn) {
return {name: 'guild', params: {groupId: 'a29da26b-37de-4a71-b0c6-48e72a900dac'} };
} else {
return {name: 'contact'};
return { name: 'guild', params: { groupId: 'a29da26b-37de-4a71-b0c6-48e72a900dac' } };
}
return { name: 'contact' };
},
},
};

View File

@@ -56,13 +56,14 @@
<script>
// @TODO:
let BASE_URL = 'https://habitica.com';
import twitter from '@/assets/svg/twitter.svg';
import facebook from '@/assets/svg/facebook.svg';
const BASE_URL = 'https://habitica.com';
export default {
data () {
let tweet = this.$t('achievementShare');
const tweet = this.$t('achievementShare');
return {
icons: Object.freeze({

View File

@@ -136,6 +136,9 @@ export default {
classes: 'content.classes',
}),
},
directives: {
markdown: markdownDirective,
},
data () {
return {
icons: Object.freeze({
@@ -147,16 +150,13 @@ export default {
selectedClass: 'warrior',
};
},
directives: {
markdown: markdownDirective,
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'choose-class');
},
clickSelectClass (heroClass) {
if (this.user.flags.classSelected && !confirm(this.$t('changeClassConfirmCost'))) return;
this.$store.dispatch('user:changeClass', {query: {class: heroClass}});
this.$store.dispatch('user:changeClass', { query: { class: heroClass } });
},
clickDisableClasses () {
this.$store.dispatch('user:disableClasses');
@@ -170,13 +170,13 @@ export default {
shield: 'shield_special_fall2019Rogue',
weapon: 'weapon_special_fall2019Rogue',
};
} else if (heroClass === 'wizard') {
} if (heroClass === 'wizard') {
return {
armor: 'armor_special_fall2019Mage',
head: 'head_special_fall2019Mage',
weapon: 'weapon_special_fall2019Mage',
};
} else if (heroClass === 'healer') {
} if (heroClass === 'healer') {
return {
armor: 'armor_special_fall2019Healer',
eyewear: 'eyewear_special_fall2019Healer',
@@ -184,14 +184,13 @@ export default {
shield: 'shield_special_fall2019Healer',
weapon: 'weapon_special_fall2019Healer',
};
} else {
}
return {
armor: 'armor_special_fall2019Warrior',
head: 'head_special_fall2019Warrior',
shield: 'shield_special_fall2019Warrior',
weapon: 'weapon_special_fall2019Warrior',
};
}
},
selectionBox (selectedClass, heroClass) {
if (selectedClass === heroClass) {

View File

@@ -34,7 +34,7 @@ export default {
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
close () {

View File

@@ -41,7 +41,7 @@ import axios from 'axios';
import Avatar from '../avatar';
import { mapState } from '@/libs/store';
import percent from '@/../../common/script/libs/percent';
import {MAX_HEALTH as maxHealth} from '@/../../common/script/constants';
import { MAX_HEALTH as maxHealth } from '@/../../common/script/constants';
import revive from '@/../../common/script/ops/revive';
export default {
@@ -54,7 +54,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
barStyle () {
return {
width: `${percent(this.user.stats.hp, maxHealth)}%`,

View File

@@ -30,7 +30,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
firstDropText () {
return this.$t('firstDrop', {
eggText: this.eggs.all.Wolf.text(),

View File

@@ -19,24 +19,24 @@
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import {mapState} from '@/libs/store';
import { mapState } from '@/libs/store';
export default {
export default {
components: {
achievementFooter,
achievementAvatar,
},
props: ['data'],
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'generic-achievement');
},
},
};
};
</script>

View File

@@ -19,18 +19,18 @@
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import {mapState} from '@/libs/store';
import { mapState } from '@/libs/store';
export default {
export default {
components: {
achievementFooter,
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
data () {
return {
@@ -42,5 +42,5 @@
this.$root.$emit('bv::hide::modal', 'just-add-water');
},
},
};
};
</script>

View File

@@ -116,20 +116,20 @@
<script>
import Avatar from '../avatar';
import { mapState } from '@/libs/store';
import {MAX_HEALTH as maxHealth} from '@/../../common/script/constants';
import { MAX_HEALTH as maxHealth } from '@/../../common/script/constants';
import styleHelper from '@/mixins/styleHelper';
import twitter from '@/assets/svg/twitter.svg';
import facebook from '@/assets/svg/facebook.svg';
let BASE_URL = 'https://habitica.com';
const BASE_URL = 'https://habitica.com';
export default {
mixins: [styleHelper],
components: {
Avatar,
},
mixins: [styleHelper],
data () {
let tweet = this.$t('levelUpShare');
const tweet = this.$t('levelUpShare');
return {
icons: Object.freeze({
twitter,
@@ -147,7 +147,7 @@ export default {
this.loadWidgets();
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
showAllocation () {
return this.$store.getters['members:hasClass'](this.user) && !this.user.preferences.automaticAllocation;
},

View File

@@ -19,18 +19,18 @@
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import {mapState} from '@/libs/store';
import { mapState } from '@/libs/store';
export default {
export default {
components: {
achievementFooter,
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
data () {
return {
@@ -42,5 +42,5 @@
this.$root.$emit('bv::hide::modal', 'lost-masterclasser');
},
},
};
};
</script>

View File

@@ -59,7 +59,7 @@
import Avatar from '../avatar';
import { mapState } from '@/libs/store';
import percent from '@/../../common/script/libs/percent';
import {MAX_HEALTH as maxHealth} from '@/../../common/script/constants';
import { MAX_HEALTH as maxHealth } from '@/../../common/script/constants';
export default {
components: {
@@ -71,7 +71,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
barStyle () {
return {
width: `${percent(this.user.stats.hp, maxHealth)}%`,

View File

@@ -19,18 +19,18 @@
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import {mapState} from '@/libs/store';
import { mapState } from '@/libs/store';
export default {
export default {
components: {
achievementFooter,
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
data () {
return {
@@ -42,5 +42,5 @@
this.$root.$emit('bv::hide::modal', 'mind-over-matter');
},
},
};
};
</script>

View File

@@ -24,22 +24,22 @@
</style>
<script>
import axios from 'axios';
import { mapState } from '@/libs/store';
import axios from 'axios';
import { mapState } from '@/libs/store';
export default {
export default {
data () {
return {
html: '',
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
async mounted () {
this.$root.$on('bv::show::modal', async (modalId) => {
this.$root.$on('bv::show::modal', async modalId => {
if (modalId !== 'new-stuff') return;
let response = await axios.get('/api/v4/news');
const response = await axios.get('/api/v4/news');
this.html = response.data.html;
});
},
@@ -52,9 +52,9 @@
this.$root.$emit('bv::hide::modal', 'new-stuff');
},
dismissAlert () {
this.$store.dispatch('user:set', {'flags.newStuff': false});
this.$store.dispatch('user:set', { 'flags.newStuff': false });
this.$root.$emit('bv::hide::modal', 'new-stuff');
},
},
};
};
</script>

View File

@@ -28,7 +28,7 @@ import questDialogDrops from '@/components/shops/quests/questDialogDrops';
import { mapState } from '@/libs/store';
import percent from '@/../../common/script/libs/percent';
import {MAX_HEALTH as maxHealth} from '@/../../common/script/constants';
import { MAX_HEALTH as maxHealth } from '@/../../common/script/constants';
export default {
components: {
@@ -41,7 +41,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
questData () {
return this.quests.quests[this.user.party.quest.completed];
},
@@ -62,7 +62,7 @@ export default {
this.close();
},
hide () {
this.$store.dispatch('user:set', {'party.quest.completed': ''});
this.$store.dispatch('user:set', { 'party.quest.completed': '' });
},
},
};

View File

@@ -48,7 +48,7 @@
import * as quests from '@/../../common/script/content/quests';
import { mapState } from '@/libs/store';
import percent from '@/../../common/script/libs/percent';
import {MAX_HEALTH as maxHealth} from '@/../../common/script/constants';
import { MAX_HEALTH as maxHealth } from '@/../../common/script/constants';
export default {
data () {
@@ -58,7 +58,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
barStyle () {
return {
width: `${percent(this.user.stats.hp, maxHealth)}%`,

View File

@@ -24,23 +24,23 @@
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import {mapState} from '@/libs/store';
import { mapState } from '@/libs/store';
export default {
export default {
components: {
achievementFooter,
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'rebirth');
},
},
};
};
</script>

View File

@@ -21,7 +21,7 @@ import { mapState } from '@/libs/store';
export default {
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
close () {

View File

@@ -38,15 +38,15 @@ export default {
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'streak');
},
suppressModals () {
let surpress = this.user.preferences.suppressModals.streak ? true : false;
this.$store.dispatch('user:set', {'preferences.suppressModals.streak': surpress});
const surpress = !!this.user.preferences.suppressModals.streak;
this.$store.dispatch('user:set', { 'preferences.suppressModals.streak': surpress });
},
},
};

View File

@@ -56,7 +56,7 @@ export default {
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
close () {

View File

@@ -49,10 +49,10 @@ export default {
markdown: markdownDirective,
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
data () {
let tweet = this.$t('wonChallengeShare');
const tweet = this.$t('wonChallengeShare');
return {
tweet,
};

View File

@@ -295,7 +295,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
...mapState(['isUserLoaded']),
getDataDisplayToolUrl () {
const base = 'https://oldgods.net/habitrpg/habitrpg_user_data_display.html';
@@ -318,7 +318,7 @@ export default {
async addMissedDay (numberOfDays) {
if (!confirm(`Are you sure you want to reset the day by ${numberOfDays} day(s)?`)) return;
let date = moment(this.user.lastCron).subtract(numberOfDays, 'days').toDate();
const date = moment(this.user.lastCron).subtract(numberOfDays, 'days').toDate();
await axios.post('/api/v4/debug/set-cron', {
lastCron: date,
@@ -356,11 +356,11 @@ export default {
addExp () {
// @TODO: Name these variables better
let exp = 0;
let five = 10 * this.user.stats.lvl;
let four = Math.pow(this.user.stats.lvl, 2) * 0.25;
let three = four + five + 139.75;
let two = three / 10;
let one = Math.round(two) * 10;
const five = 10 * this.user.stats.lvl;
const four = Math.pow(this.user.stats.lvl, 2) * 0.25;
const three = four + five + 139.75;
const two = three / 10;
const one = Math.round(two) * 10;
exp = this.user.stats.exp + one;
this.$store.dispatch('user:set', {
@@ -394,7 +394,7 @@ export default {
eventAction: 'click',
eventLabel: 'Gems > Donate',
});
this.$root.$emit('bv::show::modal', 'buy-gems', {alreadyTracked: true});
this.$root.$emit('bv::show::modal', 'buy-gems', { alreadyTracked: true });
},
},
};

View File

@@ -80,9 +80,9 @@
<script>
import hello from 'hellojs';
import { setUpAxios } from '@/libs/auth';
import debounce from 'lodash/debounce';
import isEmail from 'validator/lib/isEmail';
import { setUpAxios } from '@/libs/auth';
import facebookSquareIcon from '@/assets/svg/facebook-square.svg';
import googleIcon from '@/assets/svg/google.svg';
@@ -90,7 +90,7 @@ import googleIcon from '@/assets/svg/google.svg';
export default {
name: 'AuthForm',
data () {
let data = {
const data = {
registering: true,
username: '',
email: '',
@@ -106,13 +106,6 @@ export default {
return data;
},
mounted () {
hello.init({
facebook: process.env.FACEBOOK_KEY, // eslint-disable-line
// windows: WINDOWS_CLIENT_ID,
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line
});
},
computed: {
emailValid () {
if (this.email.length <= 3) return false;
@@ -141,6 +134,13 @@ export default {
this.validateUsername(this.username);
},
},
mounted () {
hello.init({
facebook: process.env.FACEBOOK_KEY, // eslint-disable-line
// windows: WINDOWS_CLIENT_ID,
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line
});
},
methods: {
// eslint-disable-next-line func-names
validateUsername: debounce(function (username) {
@@ -165,7 +165,7 @@ export default {
try {
const redirectUrl = `${window.location.protocol}//${window.location.host}`;
let auth = await hello(network).login({
const auth = await hello(network).login({
scope: 'email',
redirect_uri: redirectUrl, // eslint-disable-line camelcase
});
@@ -212,7 +212,7 @@ export default {
async finishAuth () {
setUpAxios();
await this.$store.dispatch('user:fetch', {forceLoad: true});
await this.$store.dispatch('user:fetch', { forceLoad: true });
this.$emit('authenticate');
},

View File

@@ -1,13 +1,13 @@
<script>
export default {
export default {
components: {},
created () {
this.logout();
},
methods: {
async logout () {
return await this.$store.dispatch('auth:logout');
},
},
created () {
this.logout();
},
};
};
</script>

View File

@@ -304,7 +304,7 @@ import googleIcon from '@/assets/svg/google.svg';
export default {
data () {
let data = {
const data = {
username: '',
email: '',
password: '',
@@ -364,29 +364,22 @@ export default {
return !this.passwordConfirmValid;
},
},
mounted () {
hello.init({
facebook: process.env.FACEBOOK_KEY, // eslint-disable-line
// windows: WINDOWS_CLIENT_ID,
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line
});
},
watch: {
$route: {
handler () {
if (this.resetPasswordSetNewOne) {
const query = this.$route.query;
const code = query.code;
const hasError = query.hasError === 'true' ? true : false;
const { query } = this.$route;
const { code } = query;
const hasError = query.hasError === 'true';
if (hasError) {
alert(query.message);
this.$router.push({name: 'login'});
this.$router.push({ name: 'login' });
return;
}
if (!code) {
alert(this.$t('invalidPasswordResetCode'));
this.$router.push({name: 'login'});
this.$router.push({ name: 'login' });
return;
}
@@ -400,6 +393,13 @@ export default {
this.validateUsername(this.username);
},
},
mounted () {
hello.init({
facebook: process.env.FACEBOOK_KEY, // eslint-disable-line
// windows: WINDOWS_CLIENT_ID,
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line
});
},
methods: {
// eslint-disable-next-line func-names
validateUsername: debounce(function (username) {
@@ -488,7 +488,7 @@ export default {
} catch (e) {} // eslint-disable-line
const redirectUrl = `${window.location.protocol}//${window.location.host}`;
let auth = await hello(network).login({
const auth = await hello(network).login({
scope: 'email',
// explicitly pass the redirect url or it might redirect to /home
redirect_uri: redirectUrl, // eslint-disable-line camelcase
@@ -568,7 +568,7 @@ export default {
this.passwordConfirm = '';
this.resetPasswordSetNewOneData.code = '';
this.resetPasswordSetNewOneData.hasError = false;
this.$router.push({name: 'login'});
this.$router.push({ name: 'login' });
},
},
};

View File

@@ -146,9 +146,9 @@ export default {
return val;
},
backgroundClass () {
let background = this.member.preferences.background;
const { background } = this.member.preferences;
let allowToShowBackground = !this.avatarOnly || this.withBackground;
const allowToShowBackground = !this.avatarOnly || this.withBackground;
if (this.overrideAvatarGear && this.overrideAvatarGear.background) {
return `background_${this.overrideAvatarGear.background}`;
@@ -169,7 +169,7 @@ export default {
};
},
skinClass () {
let baseClass = `skin_${this.member.preferences.skin}`;
const baseClass = `skin_${this.member.preferences.skin}`;
return `${baseClass}${this.member.preferences.sleep ? '_sleep' : ''}`;
},
@@ -196,19 +196,19 @@ export default {
},
hideGear (gearType) {
if (gearType === 'weapon') {
let equippedWeapon = this.member.items.gear[this.costumeClass][gearType];
const equippedWeapon = this.member.items.gear[this.costumeClass][gearType];
if (!equippedWeapon) {
return false;
}
let equippedIsTwoHanded = this.flatGear[equippedWeapon].twoHanded;
let hasOverrideShield = this.overrideAvatarGear && this.overrideAvatarGear.shield;
const equippedIsTwoHanded = this.flatGear[equippedWeapon].twoHanded;
const hasOverrideShield = this.overrideAvatarGear && this.overrideAvatarGear.shield;
return equippedIsTwoHanded && hasOverrideShield;
} else if (gearType === 'shield') {
let overrideWeapon = this.overrideAvatarGear && this.overrideAvatarGear.weapon;
let overrideIsTwoHanded = overrideWeapon && this.flatGear[overrideWeapon].twoHanded;
} if (gearType === 'shield') {
const overrideWeapon = this.overrideAvatarGear && this.overrideAvatarGear.weapon;
const overrideIsTwoHanded = overrideWeapon && this.flatGear[overrideWeapon].twoHanded;
return overrideIsTwoHanded;
}
@@ -218,10 +218,9 @@ export default {
this.$root.$emit('castEnd', this.member, 'user', e);
},
showAvatar () {
if (!this.showVisualBuffs)
return true;
if (!this.showVisualBuffs) return true;
let buffs = this.member.stats.buffs;
const { buffs } = this.member.stats;
return !buffs.snowball && !buffs.spookySparkles && !buffs.shinySeed && !buffs.seafoam;
},

View File

@@ -21,22 +21,19 @@
</template>
<script>
import appearance from '@/../../common/script/content/appearance';
import {subPageMixin} from '../../mixins/subPage';
import {userStateMixin} from '../../mixins/userState';
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
import appearance from '@/../../common/script/content/appearance';
import { subPageMixin } from '../../mixins/subPage';
import { userStateMixin } from '../../mixins/userState';
import { avatarEditorUtilies } from '../../mixins/avatarEditUtilities';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
const freeShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price === 0);
const specialShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
const freeShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price === 0);
const specialShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
export default {
props: [
'editing',
],
export default {
components: {
subMenu,
customizeOptions,
@@ -46,6 +43,9 @@
userStateMixin,
avatarEditorUtilies,
],
props: [
'editing',
],
data () {
return {
specialShirtKeys,
@@ -73,8 +73,8 @@
},
specialShirts () {
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.specialShirtKeys;
let options = keys.map(key => this.mapKeysToOption(key, 'shirt'));
const keys = this.specialShirtKeys;
const options = keys.map(key => this.mapKeysToOption(key, 'shirt'));
return options;
},
},
@@ -84,7 +84,7 @@
methods: {
},
};
};
</script>
<style scoped>

View File

@@ -23,15 +23,15 @@
</template>
<script>
import gem from '@/assets/svg/gem.svg';
import gold from '@/assets/svg/gold.svg';
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
import gem from '@/assets/svg/gem.svg';
import gold from '@/assets/svg/gold.svg';
import { avatarEditorUtilies } from '../../mixins/avatarEditUtilities';
export default {
props: ['items', 'currentValue', 'fullSet'],
export default {
mixins: [
avatarEditorUtilies,
],
props: ['items', 'currentValue', 'fullSet'],
data () {
return {
icons: Object.freeze({
@@ -45,7 +45,7 @@
this.$emit('unlock');
},
},
};
};
</script>
<style lang="scss" scoped>

View File

@@ -36,22 +36,19 @@
</template>
<script>
import appearance from '@/../../common/script/content/appearance';
import {subPageMixin} from '../../mixins/subPage';
import {userStateMixin} from '../../mixins/userState';
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
import appearance from '@/../../common/script/content/appearance';
import { subPageMixin } from '../../mixins/subPage';
import { userStateMixin } from '../../mixins/userState';
import { avatarEditorUtilies } from '../../mixins/avatarEditUtilities';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
const freeShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price === 0);
const specialShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
const freeShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price === 0);
const specialShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
export default {
props: [
'editing',
],
export default {
components: {
subMenu,
customizeOptions,
@@ -61,6 +58,9 @@
userStateMixin,
avatarEditorUtilies,
],
props: [
'editing',
],
data () {
return {
animalItemKeys: {
@@ -126,18 +126,18 @@
return items;
},
eyewear () {
let keys = [
const keys = [
'blackTopFrame', 'blueTopFrame', 'greenTopFrame', 'pinkTopFrame', 'redTopFrame', 'whiteTopFrame', 'yellowTopFrame',
'blackHalfMoon', 'blueHalfMoon', 'greenHalfMoon', 'pinkHalfMoon', 'redHalfMoon', 'whiteHalfMoon', 'yellowHalfMoon',
];
let options = keys.map(key => {
let newKey = `eyewear_special_${key}`;
let option = {};
const options = keys.map(key => {
const newKey = `eyewear_special_${key}`;
const option = {};
option.key = key;
option.active = this.user.preferences.costume ? this.user.items.gear.costume.eyewear === newKey : this.user.items.gear.equipped.eyewear === newKey;
option.class = `eyewear_special_${key}`;
option.click = () => {
let type = this.user.preferences.costume ? 'costume' : 'equipped';
const type = this.user.preferences.costume ? 'costume' : 'equipped';
return this.equip(newKey, type);
};
@@ -150,20 +150,20 @@
},
specialShirts () {
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.specialShirtKeys;
let options = keys.map(key => this.mapKeysToOption(key, 'shirt'));
const keys = this.specialShirtKeys;
const options = keys.map(key => this.mapKeysToOption(key, 'shirt'));
return options;
},
headbands () {
let keys = ['blackHeadband', 'blueHeadband', 'greenHeadband', 'pinkHeadband', 'redHeadband', 'whiteHeadband', 'yellowHeadband'];
let options = keys.map(key => {
let newKey = `headAccessory_special_${key}`;
let option = {};
const keys = ['blackHeadband', 'blueHeadband', 'greenHeadband', 'pinkHeadband', 'redHeadband', 'whiteHeadband', 'yellowHeadband'];
const options = keys.map(key => {
const newKey = `headAccessory_special_${key}`;
const option = {};
option.key = key;
option.active = this.user.preferences.costume ? this.user.items.gear.costume.headAccessory === newKey : this.user.items.gear.equipped.headAccessory === newKey;
option.class = `headAccessory_special_${option.key} headband`;
option.click = () => {
let type = this.user.preferences.costume ? 'costume' : 'equipped';
const type = this.user.preferences.costume ? 'costume' : 'equipped';
return this.equip(newKey, type);
};
return option;
@@ -171,34 +171,30 @@
return options;
},
chairs () {
let options = this.chairKeys.map(key => {
let option = {};
const options = this.chairKeys.map(key => {
const option = {};
option.key = key;
if (key === 'none') {
option.none = true;
}
option.active = this.user.preferences.chair === key;
option.class = `button_chair_${key} chair ${key.includes('handleless_') ? 'handleless' : ''}`;
option.click = () => {
return this.set({'preferences.chair': key});
};
option.click = () => this.set({ 'preferences.chair': key });
return option;
});
return options;
},
flowers () {
let keys = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
let options = keys.map(key => {
let option = {};
const keys = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
const options = keys.map(key => {
const option = {};
option.key = key;
if (key === 0) {
option.none = true;
}
option.active = this.user.preferences.hair.flower === key;
option.class = `hair_flower_${key} flower`;
option.click = () => {
return this.set({'preferences.hair.flower': key});
};
option.click = () => this.set({ 'preferences.hair.flower': key });
return option;
});
return options;
@@ -211,12 +207,12 @@
animalItems (category) {
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.animalItemKeys[category];
let options = keys.map(key => {
let newKey = `${category}_special_${key}`;
let userPurchased = this.user.items.gear.owned[newKey];
const keys = this.animalItemKeys[category];
const options = keys.map(key => {
const newKey = `${category}_special_${key}`;
const userPurchased = this.user.items.gear.owned[newKey];
let option = {};
const option = {};
option.key = key;
option.active = this.user.preferences.costume ? this.user.items.gear.costume[category] === newKey : this.user.items.gear.equipped[category] === newKey;
option.class = `headAccessory_special_${option.key} ${category}`;
@@ -235,21 +231,18 @@
option.click = () => {
if (option.gemLocked) {
return this.unlock(`items.gear.owned.${newKey}`);
} else if (option.goldLocked) {
} if (option.goldLocked) {
return this.buy(newKey);
} else {
let type = this.user.preferences.costume ? 'costume' : 'equipped';
return this.equip(newKey, type);
}
const type = this.user.preferences.costume ? 'costume' : 'equipped';
return this.equip(newKey, type);
};
return option;
});
return options;
},
animalItemsUnlockString (category) {
const keys = this.animalItemKeys[category].map(key => {
return `items.gear.owned.${category}_special_${key}`;
});
const keys = this.animalItemKeys[category].map(key => `items.gear.owned.${category}_special_${key}`);
return keys.join(',');
},
@@ -264,7 +257,7 @@
return own;
},
},
};
};
</script>
<style scoped>

View File

@@ -42,23 +42,20 @@
</template>
<script>
import appearance from '@/../../common/script/content/appearance';
import {subPageMixin} from '../../mixins/subPage';
import {userStateMixin} from '../../mixins/userState';
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
import appearanceSets from '@/../../common/script/content/appearance/sets';
import groupBy from 'lodash/groupBy';
import groupBy from 'lodash/groupBy';
import appearance from '@/../../common/script/content/appearance';
import { subPageMixin } from '../../mixins/subPage';
import { userStateMixin } from '../../mixins/userState';
import { avatarEditorUtilies } from '../../mixins/avatarEditUtilities';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
import appearanceSets from '@/../../common/script/content/appearance/sets';
const hairColorBySet = groupBy(appearance.hair.color, 'set.key');
const freeHairColorKeys = hairColorBySet[undefined].map(s => s.key);
const hairColorBySet = groupBy(appearance.hair.color, 'set.key');
const freeHairColorKeys = hairColorBySet[undefined].map(s => s.key);
export default {
props: [
'editing',
],
export default {
components: {
subMenu,
customizeOptions,
@@ -68,6 +65,9 @@
userStateMixin,
avatarEditorUtilies,
],
props: [
'editing',
],
data () {
return {
freeHairColorKeys,
@@ -115,15 +115,13 @@
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let seasonalHairColors = [];
for (let key in hairColorBySet) {
let set = hairColorBySet[key];
const seasonalHairColors = [];
for (const key in hairColorBySet) {
const set = hairColorBySet[key];
let keys = set.map(item => {
return item.key;
});
const keys = set.map(item => item.key);
let options = keys.map(optionKey => {
const options = keys.map(optionKey => {
const option = this.mapKeysToOption(optionKey, 'hair', 'color', key);
return option;
});
@@ -133,7 +131,7 @@
text = appearanceSets[key].text();
}
let compiledSet = {
const compiledSet = {
key,
options,
keys,
@@ -147,26 +145,22 @@
premiumHairColors () {
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.premiumHairColorKeys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'hair', 'color');
});
const keys = this.premiumHairColorKeys;
const options = keys.map(key => this.mapKeysToOption(key, 'hair', 'color'));
return options;
},
baseHair2 () {
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.baseHair2Keys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'hair', 'base');
});
const keys = this.baseHair2Keys;
const options = keys.map(key => this.mapKeysToOption(key, 'hair', 'base'));
return options;
},
baseHair3 () {
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.baseHair3Keys;
let options = keys.map(key => {
const keys = this.baseHair3Keys;
const options = keys.map(key => {
const option = this.mapKeysToOption(key, 'hair', 'base');
return option;
});
@@ -175,28 +169,22 @@
baseHair4 () {
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.baseHair4Keys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'hair', 'base');
});
const keys = this.baseHair4Keys;
const options = keys.map(key => this.mapKeysToOption(key, 'hair', 'base'));
return options;
},
baseHair5 () {
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.baseHair5Keys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'hair', 'mustache');
});
const keys = this.baseHair5Keys;
const options = keys.map(key => this.mapKeysToOption(key, 'hair', 'mustache'));
return options;
},
baseHair6 () {
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let keys = this.baseHair6Keys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'hair', 'beard');
});
const keys = this.baseHair6Keys;
const options = keys.map(key => this.mapKeysToOption(key, 'hair', 'beard'));
return options;
},
hairBangs () {
@@ -282,7 +270,7 @@
// If item types are specified, count them
if (types && types.length > 0) {
// Types can be undefined, so we must check them.
types.forEach((type) => {
types.forEach(type => {
if (this.user.purchased[category][type]) {
purchasedItemsLengths
.push(Object.keys(this.user.purchased[category][type]).length);
@@ -293,10 +281,10 @@
// If types are not specified, recursively
// search for purchased items in the category
const findPurchasedItems = (item) => {
const findPurchasedItems = item => {
if (typeof item === 'object') {
Object.values(item)
.forEach((innerItem) => {
.forEach(innerItem => {
if (typeof innerItem === 'boolean' && innerItem === true) {
purchasedItemsCounter += 1;
}
@@ -320,7 +308,7 @@
const allItemsLengths = [];
// Key sets must be specify correctly.
keySets.forEach((keySet) => {
keySets.forEach(keySet => {
allItemsLengths.push(Object.keys(this[keySet]).length);
});
@@ -333,7 +321,7 @@
return unpurchasedItems > 2;
},
},
};
};
</script>
<style scoped>

View File

@@ -16,28 +16,25 @@
</template>
<script>
import appearance from '@/../../common/script/content/appearance';
import {subPageMixin} from '../../mixins/subPage';
import {userStateMixin} from '../../mixins/userState';
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
import appearanceSets from '@/../../common/script/content/appearance/sets';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
import groupBy from 'lodash/groupBy';
const skinsBySet = groupBy(appearance.skin, 'set.key');
const freeSkinKeys = skinsBySet[undefined].map(s => s.key);
// const specialSkinKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
import groupBy from 'lodash/groupBy';
import appearance from '@/../../common/script/content/appearance';
import { subPageMixin } from '../../mixins/subPage';
import { userStateMixin } from '../../mixins/userState';
import { avatarEditorUtilies } from '../../mixins/avatarEditUtilities';
import appearanceSets from '@/../../common/script/content/appearance/sets';
import subMenu from './sub-menu';
import customizeOptions from './customize-options';
import gem from '@/assets/svg/gem.svg';
export default {
props: [
'editing',
],
const skinsBySet = groupBy(appearance.skin, 'set.key');
const freeSkinKeys = skinsBySet[undefined].map(s => s.key);
// const specialSkinKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
export default {
components: {
subMenu,
customizeOptions,
@@ -47,6 +44,9 @@
userStateMixin,
avatarEditorUtilies,
],
props: [
'editing',
],
data () {
return {
freeSkinKeys,
@@ -69,15 +69,13 @@
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
let seasonalSkins = [];
for (let setKey in skinsBySet) {
let set = skinsBySet[setKey];
const seasonalSkins = [];
for (const setKey in skinsBySet) {
const set = skinsBySet[setKey];
let keys = set.map(item => {
return item.key;
});
const keys = set.map(item => item.key);
let options = keys.map(optionKey => {
const options = keys.map(optionKey => {
const option = this.mapKeysToOption(optionKey, 'skin', '', setKey);
return option;
@@ -88,7 +86,7 @@
text = appearanceSets[setKey].text();
}
let compiledSet = {
const compiledSet = {
key: setKey,
options,
keys,
@@ -106,7 +104,7 @@
methods: {
},
};
};
</script>
<style scoped>

View File

@@ -10,9 +10,9 @@
</template>
<script>
export default {
export default {
props: ['items', 'activeSubPage'],
};
};
</script>
<style scoped lang="scss">

View File

@@ -13,7 +13,7 @@
</template>
<script>
export default {
export default {
props: {
categories: {
required: true,
@@ -30,5 +30,5 @@
return category.name === 'habitica_official';
},
},
};
};
</script>

View File

@@ -167,8 +167,6 @@
</style>
<script>
const TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'date', 'dateCompleted', 'history', 'id', 'streak', 'createdAt', 'challenge'];
import Vue from 'vue';
import findIndex from 'lodash/findIndex';
import cloneDeep from 'lodash/cloneDeep';
@@ -194,9 +192,9 @@ import gemIcon from '@/assets/svg/gem.svg';
import memberIcon from '@/assets/svg/member-icon.svg';
import calendarIcon from '@/assets/svg/calendar.svg';
const TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'date', 'dateCompleted', 'history', 'id', 'streak', 'createdAt', 'challenge'];
export default {
props: ['challengeId'],
mixins: [challengeMemberSearchMixin],
directives: {
markdown: markdownDirective,
},
@@ -212,6 +210,8 @@ export default {
userLink,
groupLink,
},
mixins: [challengeMemberSearchMixin],
props: ['challengeId'],
data () {
return {
searchId: '',
@@ -238,7 +238,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isMember () {
return this.user.challenges.indexOf(this.challenge._id) !== -1;
},
@@ -267,11 +267,11 @@ export default {
},
methods: {
cleanUpTask (task) {
let cleansedTask = omit(task, TASK_KEYS_TO_REMOVE);
const cleansedTask = omit(task, TASK_KEYS_TO_REMOVE);
// Copy checklists but reset to uncomplete and assign new id
if (!cleansedTask.checklist) cleansedTask.checklist = [];
cleansedTask.checklist.forEach((item) => {
cleansedTask.checklist.forEach(item => {
item.completed = false;
item.id = uuid();
});
@@ -283,16 +283,16 @@ export default {
return cleansedTask;
},
async loadChallenge () {
this.challenge = await this.$store.dispatch('challenges:getChallenge', {challengeId: this.searchId});
this.challenge = await this.$store.dispatch('challenges:getChallenge', { challengeId: this.searchId });
this.members = await this.loadMembers({ challengeId: this.searchId, includeAllPublicFields: true });
let tasks = await this.$store.dispatch('tasks:getChallengeTasks', {challengeId: this.searchId});
const tasks = await this.$store.dispatch('tasks:getChallengeTasks', { challengeId: this.searchId });
this.tasksByType = {
habit: [],
daily: [],
todo: [],
reward: [],
};
tasks.forEach((task) => {
tasks.forEach(task => {
this.tasksByType[task.type].push(task);
});
},
@@ -322,7 +322,7 @@ export default {
},
createTask (type) {
this.taskFormPurpose = 'create';
this.creatingTask = taskDefaults({type, text: ''}, this.user);
this.creatingTask = taskDefaults({ type, text: '' }, this.user);
this.workingTask = this.creatingTask;
// Necessary otherwise the first time the modal is not rendered
Vue.nextTick(() => {
@@ -337,15 +337,11 @@ export default {
this.tasksByType[task.type].push(task);
},
taskEdited (task) {
let index = findIndex(this.tasksByType[task.type], (taskItem) => {
return taskItem._id === task._id;
});
const index = findIndex(this.tasksByType[task.type], taskItem => taskItem._id === task._id);
this.tasksByType[task.type].splice(index, 1, task);
},
taskDestroyed (task) {
let index = findIndex(this.tasksByType[task.type], (taskItem) => {
return taskItem._id === task._id;
});
const index = findIndex(this.tasksByType[task.type], taskItem => taskItem._id === task._id);
this.tasksByType[task.type].splice(index, 1);
},
showMemberModal () {
@@ -360,8 +356,8 @@ export default {
},
async joinChallenge () {
this.user.challenges.push(this.searchId);
await this.$store.dispatch('challenges:joinChallenge', {challengeId: this.searchId});
await this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true});
await this.$store.dispatch('challenges:joinChallenge', { challengeId: this.searchId });
await this.$store.dispatch('tasks:fetchUserTasks', { forceLoad: true });
},
async leaveChallenge () {
this.$root.$emit('bv::show::modal', 'leave-challenge-modal');

View File

@@ -303,31 +303,23 @@
</style>
<script>
import { TAVERN_ID } from '@/../../common/script/constants';
import userLink from '../userLink';
import groupLink from '../groupLink';
import categoryTags from '../categories/categoryTags';
import markdownDirective from '@/directives/markdown';
import {mapState} from '@/libs/store';
import { TAVERN_ID } from '@/../../common/script/constants';
import userLink from '../userLink';
import groupLink from '../groupLink';
import categoryTags from '../categories/categoryTags';
import markdownDirective from '@/directives/markdown';
import { mapState } from '@/libs/store';
import gemIcon from '@/assets/svg/gem.svg';
import memberIcon from '@/assets/svg/member-icon.svg';
import calendarIcon from '@/assets/svg/calendar.svg';
import habitIcon from '@/assets/svg/habit.svg';
import todoIcon from '@/assets/svg/todo.svg';
import dailyIcon from '@/assets/svg/daily.svg';
import rewardIcon from '@/assets/svg/reward.svg';
import officialIcon from '@/assets/svg/official.svg';
import gemIcon from '@/assets/svg/gem.svg';
import memberIcon from '@/assets/svg/member-icon.svg';
import calendarIcon from '@/assets/svg/calendar.svg';
import habitIcon from '@/assets/svg/habit.svg';
import todoIcon from '@/assets/svg/todo.svg';
import dailyIcon from '@/assets/svg/daily.svg';
import rewardIcon from '@/assets/svg/reward.svg';
import officialIcon from '@/assets/svg/official.svg';
export default {
props: {
challenge: {
required: true,
},
fullLayout: {
default: true,
},
},
export default {
components: {
userLink,
groupLink,
@@ -336,6 +328,14 @@
directives: {
markdown: markdownDirective,
},
props: {
challenge: {
required: true,
},
fullLayout: {
default: true,
},
},
data () {
return {
icons: Object.freeze({
@@ -347,7 +347,7 @@
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isOwner () {
return this.challenge.leader && this.challenge.leader._id === this.user._id;
},
@@ -387,5 +387,5 @@
return group._id === TAVERN_ID;
},
},
};
};
</script>

View File

@@ -23,10 +23,10 @@ import axios from 'axios';
import Column from '../tasks/column';
export default {
props: ['challengeId'],
components: {
TaskColumn: Column,
},
props: ['challengeId'],
data () {
return {
columns: ['habit', 'daily', 'todo', 'reward'],
@@ -41,18 +41,6 @@ export default {
isAdmin: false,
};
},
mounted () {
this.$root.$on('habitica:challenge:member-progress', (data) => {
if (!data.progressMemberId) return;
this.memberId = data.progressMemberId;
this.isLeader = data.isLeader;
this.isAdmin = data.isAdmin;
this.$root.$emit('bv::show::modal', 'challenge-member-modal');
});
},
beforeDestroy () {
this.$root.$off('habitica:challenge:member-progress');
},
watch: {
async memberId (id) {
if (!id) return;
@@ -63,13 +51,25 @@ export default {
reward: [],
};
let response = await axios.get(`/api/v4/challenges/${this.challengeId}/members/${this.memberId}`);
let tasks = response.data.data.tasks;
tasks.forEach((task) => {
const response = await axios.get(`/api/v4/challenges/${this.challengeId}/members/${this.memberId}`);
const { tasks } = response.data.data;
tasks.forEach(task => {
this.tasksByType[task.type].push(task);
});
},
},
mounted () {
this.$root.$on('habitica:challenge:member-progress', data => {
if (!data.progressMemberId) return;
this.memberId = data.progressMemberId;
this.isLeader = data.isLeader;
this.isAdmin = data.isAdmin;
this.$root.$emit('bv::show::modal', 'challenge-member-modal');
});
},
beforeDestroy () {
this.$root.$off('habitica:challenge:member-progress');
},
methods: {
async closeChallenge () {
this.challenge = await this.$store.dispatch('challenges:selectChallengeWinner', {

View File

@@ -138,12 +138,12 @@ import { TAVERN_ID, MIN_SHORTNAME_SIZE_FOR_CHALLENGES, MAX_SUMMARY_SIZE_FOR_CHAL
import { mapState } from '@/libs/store';
export default {
props: ['groupId'],
directives: {
markdown: markdownDirective,
},
props: ['groupId'],
data () {
let categoryOptions = [
const categoryOptions = [
{
label: 'habitica_official',
key: 'habitica_official',
@@ -201,11 +201,11 @@ export default {
key: 'time_management',
},
];
let hashedCategories = {};
categoryOptions.forEach((category) => {
const hashedCategories = {};
categoryOptions.forEach(category => {
hashedCategories[category.key] = category.label;
});
let categoriesHashByKey = hashedCategories;
const categoriesHashByKey = hashedCategories;
return {
workingChallenge: {
@@ -233,24 +233,6 @@ export default {
groups: [],
};
},
mounted () {
this.$root.$on('habitica:clone-challenge', (data) => {
if (!data.challenge) return;
this.cloning = true;
this.cloningChallengeId = data.challenge._id;
this.$store.state.challengeOptions.workingChallenge = Object.assign({}, this.$store.state.challengeOptions.workingChallenge, data.challenge);
this.$root.$emit('bv::show::modal', 'challenge-modal');
});
this.$root.$on('habitica:update-challenge', (data) => {
if (!data.challenge) return;
this.cloning = false;
this.$store.state.challengeOptions.workingChallenge = Object.assign({}, this.$store.state.challengeOptions.workingChallenge, data.challenge);
this.$root.$emit('bv::show::modal', 'challenge-modal');
});
},
beforeDestroy () {
this.$root.$off('habitica:clone-challenge');
},
watch: {
user () {
if (!this.challenge) this.workingChallenge.leader = this.user._id;
@@ -262,8 +244,26 @@ export default {
this.setUpWorkingChallenge();
},
},
mounted () {
this.$root.$on('habitica:clone-challenge', data => {
if (!data.challenge) return;
this.cloning = true;
this.cloningChallengeId = data.challenge._id;
this.$store.state.challengeOptions.workingChallenge = { ...this.$store.state.challengeOptions.workingChallenge, ...data.challenge };
this.$root.$emit('bv::show::modal', 'challenge-modal');
});
this.$root.$on('habitica:update-challenge', data => {
if (!data.challenge) return;
this.cloning = false;
this.$store.state.challengeOptions.workingChallenge = { ...this.$store.state.challengeOptions.workingChallenge, ...data.challenge };
this.$root.$emit('bv::show::modal', 'challenge-modal');
});
},
beforeDestroy () {
this.$root.$off('habitica:clone-challenge');
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
creating () {
return !this.workingChallenge.id;
},
@@ -274,19 +274,18 @@ export default {
return this.$t('editingChallenge');
},
charactersRemaining () {
let currentLength = this.workingChallenge.summary ? this.workingChallenge.summary.length : 0;
const currentLength = this.workingChallenge.summary ? this.workingChallenge.summary.length : 0;
return MAX_SUMMARY_SIZE_FOR_CHALLENGES - currentLength;
},
maxPrize () {
let userBalance = this.user.balance || 0;
userBalance = userBalance * 4;
userBalance *= 4;
let groupBalance = 0;
let group;
this.groups.forEach(item => {
if (item._id === this.workingChallenge.group) {
group = item;
return;
}
});
@@ -301,14 +300,13 @@ export default {
return 0;
},
insufficientGemsForTavernChallenge () {
let balance = this.user.balance || 0;
let isForTavern = this.workingChallenge.group === TAVERN_ID;
const balance = this.user.balance || 0;
const isForTavern = this.workingChallenge.group === TAVERN_ID;
if (isForTavern) {
return balance <= 0;
} else {
return false;
}
return false;
},
challenge () {
return this.$store.state.challengeOptions.workingChallenge;
@@ -342,7 +340,7 @@ export default {
if (!this.challenge) return;
this.workingChallenge = Object.assign({}, this.workingChallenge, this.challenge);
this.workingChallenge = { ...this.workingChallenge, ...this.challenge };
// @TODO: Should we use a separate field? I think the API expects `group` but it is confusing
this.workingChallenge.group = this.workingChallenge.group._id;
this.workingChallenge.categories = [];
@@ -381,7 +379,7 @@ export default {
async createChallenge () {
this.loading = true;
// @TODO: improve error handling, add it to updateChallenge, make errors translatable. Suggestion: `<% fieldName %> is required` where possible, where `fieldName` is inserted as the translatable string that's used for the field header.
let errors = [];
const errors = [];
if (!this.workingChallenge.name) errors.push(this.$t('nameRequired'));
if (this.workingChallenge.shortName.length < MIN_SHORTNAME_SIZE_FOR_CHALLENGES) errors.push(this.$t('tagTooShort'));
@@ -398,17 +396,17 @@ export default {
}
this.workingChallenge.timestamp = new Date().getTime();
let categoryKeys = this.workingChallenge.categories;
let serverCategories = [];
const categoryKeys = this.workingChallenge.categories;
const serverCategories = [];
categoryKeys.forEach(key => {
let catName = this.categoriesHashByKey[key];
const catName = this.categoriesHashByKey[key];
serverCategories.push({
slug: key,
name: catName,
});
});
let challengeDetails = clone(this.workingChallenge);
const challengeDetails = clone(this.workingChallenge);
challengeDetails.categories = serverCategories;
let challenge;
@@ -419,13 +417,11 @@ export default {
});
this.cloningChallengeId = '';
} else {
challenge = await this.$store.dispatch('challenges:createChallenge', {challenge: challengeDetails});
challenge = await this.$store.dispatch('challenges:createChallenge', { challenge: challengeDetails });
}
// Update Group Prize
let challengeGroup = this.groups.find(group => {
return group._id === this.workingChallenge.group;
});
const challengeGroup = this.groups.find(group => group._id === this.workingChallenge.group);
// @TODO: Share with server
const prizeCost = this.workingChallenge.prize / 4;
@@ -435,7 +431,7 @@ export default {
// Group pays for all of prize
} else if (challengeGroup && userIsLeader && challengeGroup.balance > 0) {
// User pays remainder of prize cost after group
let remainder = prizeCost - challengeGroup.balance;
const remainder = prizeCost - challengeGroup.balance;
this.user.balance -= remainder;
} else {
// User pays for all of prize
@@ -449,24 +445,24 @@ export default {
this.$router.push(`/challenges/${challenge._id}`);
},
updateChallenge () {
let categoryKeys = this.workingChallenge.categories;
let serverCategories = [];
const categoryKeys = this.workingChallenge.categories;
const serverCategories = [];
categoryKeys.forEach(key => {
let newKey = key.trim();
let catName = this.categoriesHashByKey[newKey];
const newKey = key.trim();
const catName = this.categoriesHashByKey[newKey];
serverCategories.push({
slug: newKey,
name: catName,
});
});
let challengeDetails = clone(this.workingChallenge);
const challengeDetails = clone(this.workingChallenge);
challengeDetails.categories = serverCategories;
this.$emit('updatedChallenge', {
challenge: challengeDetails,
});
this.$store.dispatch('challenges:updateChallenge', {challenge: challengeDetails});
this.$store.dispatch('challenges:updateChallenge', { challenge: challengeDetails });
this.resetWorkingChallenge();
this.$root.$emit('bv::hide::modal', 'challenge-modal');
},

View File

@@ -74,10 +74,10 @@ div
import memberSearchDropdown from '@/components/members/memberSearchDropdown';
export default {
props: ['challengeId', 'members', 'prize'],
components: {
memberSearchDropdown,
},
props: ['challengeId', 'members', 'prize'],
data () {
return {
winner: {},

View File

@@ -66,6 +66,8 @@
</style>
<script>
import MugenScroll from 'vue-mugen-scroll';
import debounce from 'lodash/debounce';
import { mapState } from '@/libs/store';
import Sidebar from './sidebar';
@@ -75,18 +77,15 @@ import challengeUtilities from '@/mixins/challengeUtilities';
import positiveIcon from '@/assets/svg/positive.svg';
import MugenScroll from 'vue-mugen-scroll';
import debounce from 'lodash/debounce';
export default {
mixins: [challengeUtilities],
components: {
Sidebar,
ChallengeItem,
challengeModal,
MugenScroll,
},
mixins: [challengeUtilities],
data () {
return {
loading: true,
@@ -127,7 +126,7 @@ export default {
this.loadChallenges();
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
filteredChallenges () {
return this.challenges;
},

View File

@@ -38,21 +38,21 @@ div
</style>
<script>
import challengeModal from './challengeModal';
import {mapState} from '@/libs/store';
import markdownDirective from '@/directives/markdown';
import challengeModal from './challengeModal';
import { mapState } from '@/libs/store';
import markdownDirective from '@/directives/markdown';
import challengeItem from './challengeItem';
import challengeIcon from '@/assets/svg/challenge.svg';
import challengeItem from './challengeItem';
import challengeIcon from '@/assets/svg/challenge.svg';
export default {
props: ['groupId'],
export default {
components: {
challengeModal,
challengeItem,
},
props: ['groupId'],
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
data () {
return {
@@ -66,19 +66,19 @@ div
directives: {
markdown: markdownDirective,
},
mounted () {
this.loadChallenges();
},
watch: {
async groupId () {
this.loadChallenges();
},
},
mounted () {
this.loadChallenges();
},
methods: {
async loadChallenges () {
this.groupIdForChallenges = this.groupId;
if (this.groupId === 'party' && this.user.party._id) this.groupIdForChallenges = this.user.party._id;
this.challenges = await this.$store.dispatch('challenges:getGroupChallenges', {groupId: this.groupIdForChallenges});
this.challenges = await this.$store.dispatch('challenges:getGroupChallenges', { groupId: this.groupIdForChallenges });
},
createChallenge () {
this.$root.$emit('bv::show::modal', 'challenge-modal');
@@ -88,5 +88,5 @@ div
this.challenges.push(challenge);
},
},
};
};
</script>

View File

@@ -19,22 +19,20 @@ import { mapState } from '@/libs/store';
import notifications from '@/mixins/notifications';
export default {
props: ['challengeId'],
mixins: [notifications],
props: ['challengeId'],
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
async leaveChallenge (keep) {
let index = findIndex(this.user.challenges, (id) => {
return id === this.challengeId;
});
const index = findIndex(this.user.challenges, id => id === this.challengeId);
this.user.challenges.splice(index, 1);
await this.$store.dispatch('challenges:leaveChallenge', {
challengeId: this.challengeId,
keep,
});
await this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true});
await this.$store.dispatch('tasks:fetchUserTasks', { forceLoad: true });
this.close();
},
close () {

View File

@@ -80,6 +80,8 @@
</style>
<script>
import MugenScroll from 'vue-mugen-scroll';
import debounce from 'lodash/debounce';
import { mapState } from '@/libs/store';
import Sidebar from './sidebar';
import ChallengeItem from './challengeItem';
@@ -88,18 +90,16 @@ import challengeUtilities from '@/mixins/challengeUtilities';
import challengeIcon from '@/assets/svg/challenge.svg';
import positiveIcon from '@/assets/svg/positive.svg';
import MugenScroll from 'vue-mugen-scroll';
import debounce from 'lodash/debounce';
export default {
mixins: [challengeUtilities],
components: {
Sidebar,
ChallengeItem,
challengeModal,
MugenScroll,
},
mixins: [challengeUtilities],
data () {
return {
icons: Object.freeze({
@@ -141,15 +141,15 @@ export default {
this.loadChallenges();
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
filteredChallenges () {
const filters = this.filters;
const user = this.user;
const { filters } = this;
const { user } = this;
return this.challenges.filter(challenge => {
let isMember = true;
let filteringRole = filters.roles && filters.roles.length > 0;
const filteringRole = filters.roles && filters.roles.length > 0;
if (filteringRole && filters.roles.indexOf('participating') !== -1) {
isMember = this.isMemberOfChallenge(user, challenge);
}

View File

@@ -66,6 +66,7 @@ import tier9 from '@/assets/svg/tier-staff.svg';
import tierNPC from '@/assets/svg/tier-npc.svg';
export default {
mixins: [styleHelper],
props: ['selections', 'text', 'caretPosition', 'coords', 'chat', 'textbox'],
data () {
return {
@@ -93,7 +94,7 @@ export default {
computed: {
autocompleteStyle () {
function heightToUse (textBox, topCoords) {
let textBoxHeight = textBox['user-entry'].clientHeight;
const textBoxHeight = textBox['user-entry'].clientHeight;
return topCoords < textBoxHeight ? topCoords + 30 : textBoxHeight + 10;
}
return {
@@ -113,15 +114,10 @@ export default {
this.currentSearch = this.atRegex.exec(this.text)[0]; // eslint-disable-line vue/no-side-effects-in-computed-properties
this.currentSearch = this.currentSearch.substring(1, this.currentSearch.length); // eslint-disable-line vue/no-side-effects-in-computed-properties
return this.tmpSelections.filter((option) => {
return option.displayName.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1 || option.username && option.username.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1;
}).slice(0, 4);
return this.tmpSelections.filter(option => option.displayName.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1 || option.username && option.username.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1).slice(0, 4);
},
},
mounted () {
this.grabUserNames();
},
watch: {
text (newText) {
if (!newText[newText.length - 1] || newText[newText.length - 1] === ' ') {
@@ -143,6 +139,9 @@ export default {
this.grabUserNames();
},
},
mounted () {
this.grabUserNames();
},
methods: {
resetDefaults () {
// Mounted is not called when switching between group pages because they have the
@@ -153,9 +152,9 @@ export default {
this.resetSelection();
},
grabUserNames () {
let usersThatMessage = groupBy(this.chat, 'user');
for (let userKey in usersThatMessage) {
let systemMessage = userKey === 'undefined';
const usersThatMessage = groupBy(this.chat, 'user');
for (const userKey in usersThatMessage) {
const systemMessage = userKey === 'undefined';
if (!systemMessage && this.tmpSelections.indexOf(userKey) === -1) {
this.tmpSelections.push({
displayName: userKey,
@@ -204,18 +203,18 @@ export default {
selectNext () {
if (this.searchResults.length > 0) {
this.clearHover();
this.selected = this.selected === null ?
0 :
(this.selected + 1) % this.searchResults.length;
this.selected = this.selected === null
? 0
: (this.selected + 1) % this.searchResults.length;
this.searchResults[this.selected].hover = true;
}
},
selectPrevious () {
if (this.searchResults.length > 0) {
this.clearHover();
this.selected = this.selected === null ?
this.searchResults.length - 1 :
(this.selected - 1 + this.searchResults.length) % this.searchResults.length;
this.selected = this.selected === null
? this.searchResults.length - 1
: (this.selected - 1 + this.searchResults.length) % this.searchResults.length;
this.searchResults[this.selected].hover = true;
}
},
@@ -231,6 +230,5 @@ export default {
this.resetSelection();
},
},
mixins: [styleHelper],
};
</script>

View File

@@ -140,7 +140,16 @@ import { highlightUsers } from '../../libs/highlightUsers';
import { CHAT_FLAG_LIMIT_FOR_HIDING, CHAT_FLAG_FROM_SHADOW_MUTE } from '@/../../common/script/constants';
export default {
components: {userLink},
components: { userLink },
filters: {
timeAgo (value) {
return moment(value).fromNow();
},
date (value) {
// @TODO: Vue doesn't support this so we cant user preference
return moment(value).toDate().toString();
},
},
props: {
msg: {},
inbox: {
@@ -161,20 +170,11 @@ export default {
reported: false,
};
},
filters: {
timeAgo (value) {
return moment(value).fromNow();
},
date (value) {
// @TODO: Vue doesn't support this so we cant user preference
return moment(value).toDate().toString();
},
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isUserMentioned () {
const message = this.msg;
const user = this.user;
const { user } = this;
if (message.hasOwnProperty('highlight')) return message.highlight;
@@ -190,7 +190,7 @@ export default {
const pattern = `@(${escapedUsername}|${escapedDisplayName})(\\b)`;
const precedingChar = messageText.substring(mentioned - 1, mentioned);
if (mentioned === 0 || precedingChar.trim() === '' || precedingChar === '@') {
let regex = new RegExp(pattern, 'i');
const regex = new RegExp(pattern, 'i');
message.highlight = regex.test(messageText);
}
@@ -201,8 +201,8 @@ export default {
if (!message.likes) return 0;
let likeCount = 0;
for (let key in message.likes) {
let like = message.likes[key];
for (const key in message.likes) {
const like = message.likes[key];
if (like) likeCount += 1;
}
return likeCount;
@@ -217,9 +217,14 @@ export default {
return 'Message hidden (shadow-muted)';
},
},
mounted () {
this.CHAT_FLAG_LIMIT_FOR_HIDING = CHAT_FLAG_LIMIT_FOR_HIDING;
this.CHAT_FLAG_FROM_SHADOW_MUTE = CHAT_FLAG_FROM_SHADOW_MUTE;
this.$emit('chat-card-mounted', this.msg.id);
},
methods: {
async like () {
let message = cloneDeep(this.msg);
const message = cloneDeep(this.msg);
await this.$store.dispatch('chat:like', {
groupId: this.groupId,
@@ -279,10 +284,5 @@ export default {
return habiticaMarkdown.render(String(text));
},
},
mounted () {
this.CHAT_FLAG_LIMIT_FOR_HIDING = CHAT_FLAG_LIMIT_FOR_HIDING;
this.CHAT_FLAG_FROM_SHADOW_MUTE = CHAT_FLAG_FROM_SHADOW_MUTE;
this.$emit('chat-card-mounted', this.msg.id);
},
};
</script>

View File

@@ -140,15 +140,20 @@
<script>
import moment from 'moment';
import axios from 'axios';
import { mapState } from '@/libs/store';
import debounce from 'lodash/debounce';
import findIndex from 'lodash/findIndex';
import { mapState } from '@/libs/store';
import Avatar from '../avatar';
import copyAsTodoModal from './copyAsTodoModal';
import chatCard from './chatCard';
export default {
components: {
copyAsTodoModal,
chatCard,
Avatar,
},
props: {
chat: {},
inbox: {
@@ -162,20 +167,6 @@ export default {
isLoading: Boolean,
canLoadMore: Boolean,
},
components: {
copyAsTodoModal,
chatCard,
Avatar,
},
mounted () {
this.loadProfileCache();
},
created () {
window.addEventListener('scroll', this.handleScroll);
},
destroyed () {
window.removeEventListener('scroll', this.handleScroll);
},
data () {
return {
currentDayDividerDisplay: moment().day(),
@@ -187,8 +178,17 @@ export default {
lastOffset: -1,
};
},
mounted () {
this.loadProfileCache();
},
created () {
window.addEventListener('scroll', this.handleScroll);
},
destroyed () {
window.removeEventListener('scroll', this.handleScroll);
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
// @TODO: We need a different lazy load mechnism.
// But honestly, adding a paging route to chat would solve this
messages () {
@@ -201,7 +201,7 @@ export default {
this.loadProfileCache(window.scrollY / 1000);
},
async triggerLoad () {
const container = this.$refs.container;
const { container } = this.$refs;
// get current offset
this.lastOffset = container.scrollTop - (container.scrollHeight - container.clientHeight);
@@ -226,7 +226,7 @@ export default {
if (this.loading) return;
this.loading = true;
let promises = [];
const promises = [];
const noProfilesLoaded = Object.keys(this.cachedProfileData).length === 0;
// @TODO: write an explination
@@ -237,9 +237,9 @@ export default {
return;
}
let aboutToCache = {};
const aboutToCache = {};
this.messages.forEach(message => {
let uuid = message.uuid;
const { uuid } = message;
if (message.userStyles) {
this.$set(this.cachedProfileData, uuid, message.userStyles);
@@ -253,21 +253,21 @@ export default {
}
});
let results = await Promise.all(promises);
const results = await Promise.all(promises);
results.forEach(result => {
// We could not load the user. Maybe they were deleted. So, let's cache empty so we don't try again
if (!result || !result.data || result.status >= 400) {
return;
}
let userData = result.data.data;
const userData = result.data.data;
this.$set(this.cachedProfileData, userData._id, userData);
});
// Merge in any attempts that were rejected so we don't attempt again
for (let uuid in aboutToCache) {
for (const uuid in aboutToCache) {
if (!this.cachedProfileData[uuid]) {
this.$set(this.cachedProfileData, uuid, {rejected: true});
this.$set(this.cachedProfileData, uuid, { rejected: true });
}
}
@@ -293,22 +293,21 @@ export default {
type: 'error',
timeout: false,
});
} else {
}
this.cachedProfileData[memberId] = result.data.data;
profile = result.data.data;
}
}
// Open the modal only if the data is available
if (profile && !profile.rejected) {
this.$router.push({name: 'userProfile', params: {userId: profile._id}});
this.$router.push({ name: 'userProfile', params: { userId: profile._id } });
}
},
itemWasMounted: debounce(function itemWasMounted () {
if (this.handleScrollBack) {
this.handleScrollBack = false;
const container = this.$refs.container;
const { container } = this.$refs;
const offset = container.scrollHeight - container.clientHeight;
const newOffset = offset + this.lastOffset;
@@ -319,9 +318,7 @@ export default {
}
}, 50),
messageLiked (message) {
const chatIndex = findIndex(this.chat, chatMessage => {
return chatMessage.id === message.id;
});
const chatIndex = findIndex(this.chat, chatMessage => chatMessage.id === message.id);
this.chat.splice(chatIndex, 1, message);
},
messageRemoved (message) {
@@ -330,9 +327,7 @@ export default {
return;
}
const chatIndex = findIndex(this.chat, chatMessage => {
return chatMessage.id === message.id;
});
const chatIndex = findIndex(this.chat, chatMessage => chatMessage.id === message.id);
this.chat.splice(chatIndex, 1);
},
},

View File

@@ -59,11 +59,10 @@ export default {
groupPath () {
if (this.groupId === TAVERN_ID) {
return `${baseUrl}/groups/tavern`;
} else if (this.groupType === 'party') {
} if (this.groupType === 'party') {
return `${baseUrl}/party`;
} else {
return `${baseUrl}/groups/guild/${this.groupId}`;
}
return `${baseUrl}/groups/guild/${this.groupId}`;
},
close () {
this.$root.$emit('bv::hide::modal', 'copyAsTodo');

View File

@@ -66,15 +66,15 @@ import notifications from '@/mixins/notifications';
import markdownDirective from '@/directives/markdown';
export default {
mixins: [notifications],
directives: {
markdown: markdownDirective,
},
mixins: [notifications],
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
reportData () {
let reportMessage = this.abuseObject.user;
let isSystemMessage = this.abuseObject.uuid === 'system';
const isSystemMessage = this.abuseObject.uuid === 'system';
if (isSystemMessage) reportMessage = this.$t('systemMessage');
return {
name: `<span class='text-danger'>${reportMessage}</span>`,
@@ -82,7 +82,7 @@ export default {
},
},
data () {
let abuseFlagModalBody = {
const abuseFlagModalBody = {
firstLinkStart: '<a href="/static/community-guidelines" target="_blank">',
secondLinkStart: '<a href="/static/terms" target="_blank">',
linkEnd: '</a>',
@@ -108,7 +108,7 @@ export default {
async reportAbuse () {
this.text(this.$t(this.groupId === 'privateMessage' ? 'pmReported' : 'abuseReported'));
let result = await this.$store.dispatch('chat:flag', {
const result = await this.$store.dispatch('chat:flag', {
groupId: this.groupId,
chatId: this.abuseObject.id,
comment: this.reportComment,

View File

@@ -731,12 +731,11 @@ import pin from '@/assets/svg/pin.svg';
import arrowRight from '@/assets/svg/arrow_right.svg';
import arrowLeft from '@/assets/svg/arrow_left.svg';
import isPinned from '@/../../common/script/libs/isPinned';
import {avatarEditorUtilies} from '../mixins/avatarEditUtilities';
import { avatarEditorUtilies } from '../mixins/avatarEditUtilities';
import content from '@/../../common/script/content/index';
export default {
mixins: [guide, notifications, avatarEditorUtilies],
components: {
avatar,
toggleSwitch,
@@ -748,13 +747,9 @@ export default {
subMenu,
},
mounted () {
if (this.editing) this.modalPage = 2;
// Buy modal is global, so we listen at root. I'd like to not
this.$root.$on('buyModal::boughtItem', this.backgroundPurchased);
},
mixins: [guide, notifications, avatarEditorUtilies],
data () {
let backgroundShopSets = shops.getBackgroundShopSets();
const backgroundShopSets = shops.getBackgroundShopSets();
return {
loading: false,
@@ -786,12 +781,10 @@ export default {
},
],
bgSubMenuItems: ['2019', '2018', '2017', '2016', '2015', '2014'].map(y =>
({
bgSubMenuItems: ['2019', '2018', '2017', '2016', '2015', '2014'].map(y => ({
id: y,
label: y,
})
),
})),
};
},
watch: {
@@ -806,8 +799,13 @@ export default {
this.$store.state.avatarEditorOptions.subpage = '';
},
},
mounted () {
if (this.editing) this.modalPage = 2;
// Buy modal is global, so we listen at root. I'd like to not
this.$root.$on('buyModal::boughtItem', this.backgroundPurchased);
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
editing () {
@@ -818,7 +816,7 @@ export default {
},
backgroundShopSetsByYear () {
// @TODO: add dates to backgrounds
let backgroundShopSetsByYear = {
const backgroundShopSetsByYear = {
2014: [],
2015: [],
2016: [],
@@ -830,12 +828,12 @@ export default {
// Hack to force update for now until we restructure the data
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
this.backgroundShopSets.forEach((set) => {
let year = set.identifier.substr(set.identifier.length - 4);
this.backgroundShopSets.forEach(set => {
const year = set.identifier.substr(set.identifier.length - 4);
if (!backgroundShopSetsByYear[year]) return;
let setOwnedByUser = false;
for (let key in set.items) {
for (const key in set.items) {
if (this.user.purchased.background[key]) setOwnedByUser = true;
}
set.userOwns = setOwnedByUser;
@@ -845,13 +843,13 @@ export default {
return backgroundShopSetsByYear;
},
ownedBackgrounds () {
let ownedBackgrounds = [];
const ownedBackgrounds = [];
// Hack to force update for now until we restructure the data
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
this.backgroundShopSets.forEach((set) => {
set.items.forEach((bg) => {
this.backgroundShopSets.forEach(set => {
set.items.forEach(bg => {
if (this.user.purchased.background[bg.key]) {
ownedBackgrounds.push(bg);
}
@@ -900,8 +898,8 @@ export default {
});
// @TODO: Move to the action
let response = await axios.post('/api/v4/tasks/user', tasksToCreate);
let tasks = response.data.data;
const response = await axios.post('/api/v4/tasks/user', tasksToCreate);
const tasks = response.data.data;
tasks.forEach(task => {
this.$store.state.user.data.tasksOrder[`${task.type}s`].unshift(task._id);
this.$store.state.tasks.data[`${task.type}s`].unshift(task);
@@ -926,7 +924,7 @@ export default {
let setOwnedByUser = false;
for (let key in set) {
let value = set[key];
const value = set[key];
if (type === 'background') key = value.key;
if (this.user.purchased[type][key]) setOwnedByUser = true;
}
@@ -948,8 +946,8 @@ export default {
return isPinned(this.user, bg);
},
togglePinned (bg) {
if (!this.$store.dispatch('user:togglePinnedItem', {type: bg.pinType, path: bg.path})) {
this.text(this.$t('unpinnedItem', {item: bg.text}));
if (!this.$store.dispatch('user:togglePinnedItem', { type: bg.pinType, path: bg.path })) {
this.text(this.$t('unpinnedItem', { item: bg.text }));
}
},
backgroundSelected (bg) {

View File

@@ -62,7 +62,7 @@ export default {
}
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isLeader () {
return this.user._id === this.group.leader._id;
},
@@ -81,8 +81,8 @@ export default {
},
methods: {
async loadGroup () {
let group = await this.$store.dispatch('guilds:getGroup', {groupId: this.groupId});
this.group = Object.assign({}, group);
const group = await this.$store.dispatch('guilds:getGroup', { groupId: this.groupId });
this.group = { ...group };
},
upgradeGroup () {
this.$store.state.upgradingGroup = this.group;

View File

@@ -79,10 +79,10 @@ import amazonButton from '@/components/payments/amazonButton';
import creditCardIcon from '@/assets/svg/credit-card-icon.svg';
export default {
mixins: [paymentsMixin],
components: {
amazonButton,
},
mixins: [paymentsMixin],
data () {
return {
amazonPayments: {},
@@ -110,7 +110,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
newGroupIsReady () {
return Boolean(this.newGroup.name);
},
@@ -131,7 +131,7 @@ export default {
},
pay (paymentMethod) {
const subscriptionKey = 'group_monthly';
let paymentData = {
const paymentData = {
subscription: subscriptionKey,
coupon: null,
};

View File

@@ -213,7 +213,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
shown () {

View File

@@ -22,20 +22,18 @@ import SecondaryMenu from '@/components/secondaryMenu';
import { mapState } from '@/libs/store';
export default {
props: ['groupId'],
components: {
SecondaryMenu,
groupFormModal,
},
props: ['groupId'],
computed: {
...mapState({
user: 'user.data',
groupPlans: 'groupPlans',
}),
currentGroup () {
let groupFound = this.groupPlans.find(group => {
return group._id === this.groupId;
});
const groupFound = this.groupPlans.find(group => group._id === this.groupId);
return groupFound;
},

View File

@@ -67,6 +67,10 @@
</style>
<script>
import Vue from 'vue';
import cloneDeep from 'lodash/cloneDeep';
import findIndex from 'lodash/findIndex';
import groupBy from 'lodash/groupBy';
import taskDefaults from '@/../../common/script/libs/taskDefaults';
import TaskColumn from '../tasks/column';
import TaskModal from '../tasks/taskModal';
@@ -80,19 +84,15 @@ import dailyIcon from '@/assets/svg/daily.svg';
import todoIcon from '@/assets/svg/todo.svg';
import rewardIcon from '@/assets/svg/reward.svg';
import Vue from 'vue';
import cloneDeep from 'lodash/cloneDeep';
import findIndex from 'lodash/findIndex';
import groupBy from 'lodash/groupBy';
import { mapState } from '@/libs/store';
export default {
props: ['groupId'],
components: {
TaskColumn,
TaskModal,
GroupPlanOverviewModal,
},
props: ['groupId'],
data () {
return {
openCreateBtn: false,
@@ -143,7 +143,7 @@ export default {
}
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
tagsByType () {
const userTags = this.user.tags;
const tagsByType = {
@@ -194,22 +194,22 @@ export default {
groupId: this.searchId,
});
let members = await this.$store.dispatch('members:getGroupMembers', {groupId: this.searchId});
const members = await this.$store.dispatch('members:getGroupMembers', { groupId: this.searchId });
this.group.members = members;
let tasks = await this.$store.dispatch('tasks:getGroupTasks', {
const tasks = await this.$store.dispatch('tasks:getGroupTasks', {
groupId: this.searchId,
});
let groupedApprovals = await this.loadApprovals();
const groupedApprovals = await this.loadApprovals();
tasks.forEach((task) => {
tasks.forEach(task => {
if (groupedApprovals[task._id] && groupedApprovals[task._id].length > 0) task.approvals = groupedApprovals[task._id];
this.tasksByType[task.type].push(task);
});
},
async loadApprovals () {
let approvalRequests = await this.$store.dispatch('tasks:getGroupApprovals', {
const approvalRequests = await this.$store.dispatch('tasks:getGroupApprovals', {
groupId: this.searchId,
});
@@ -229,10 +229,8 @@ export default {
groupId: this.searchId,
});
completedTodos.forEach((task) => {
const existingTaskIndex = findIndex(this.tasksByType.todo, (todo) => {
return todo._id === task._id;
});
completedTodos.forEach(task => {
const existingTaskIndex = findIndex(this.tasksByType.todo, todo => todo._id === task._id);
if (existingTaskIndex === -1) {
this.tasksByType.todo.push(task);
}
@@ -241,7 +239,7 @@ export default {
createTask (type) {
this.openCreateBtn = false;
this.taskFormPurpose = 'create';
this.creatingTask = taskDefaults({type, text: ''}, this.user);
this.creatingTask = taskDefaults({ type, text: '' }, this.user);
this.workingTask = this.creatingTask;
// Necessary otherwise the first time the modal is not rendered
Vue.nextTick(() => {
@@ -253,15 +251,11 @@ export default {
this.tasksByType[task.type].push(task);
},
taskEdited (task) {
let index = findIndex(this.tasksByType[task.type], (taskItem) => {
return taskItem._id === task._id;
});
const index = findIndex(this.tasksByType[task.type], taskItem => taskItem._id === task._id);
this.tasksByType[task.type].splice(index, 1, task);
},
taskDestroyed (task) {
let index = findIndex(this.tasksByType[task.type], (taskItem) => {
return taskItem._id === task._id;
});
const index = findIndex(this.tasksByType[task.type], taskItem => taskItem._id === task._id);
this.tasksByType[task.type].splice(index, 1);
},
cancelTaskModal () {
@@ -289,12 +283,12 @@ export default {
this.closeFilterPanel();
},
applyFilters () {
const temporarilySelectedTags = this.temporarilySelectedTags;
const { temporarilySelectedTags } = this;
this.selectedTags = temporarilySelectedTags.slice();
this.closeFilterPanel();
},
toggleTag (tag) {
const temporarilySelectedTags = this.temporarilySelectedTags;
const { temporarilySelectedTags } = this;
const tagI = temporarilySelectedTags.indexOf(tag.id);
if (tagI === -1) {
temporarilySelectedTags.push(tag.id);

View File

@@ -6,20 +6,20 @@
</template>
<script>
import { TAVERN_ID } from '@/../../common/script/constants';
import { TAVERN_ID } from '@/../../common/script/constants';
export default {
export default {
props: ['group'],
methods: {
goToGroup () {
if (this.group.type === 'party') {
this.$router.push({name: 'party'});
this.$router.push({ name: 'party' });
} else if (this.group._id === TAVERN_ID) {
this.$router.push({name: 'tavern'});
this.$router.push({ name: 'tavern' });
} else {
this.$router.push({name: 'guild', params: {groupId: this.group._id}});
this.$router.push({ name: 'guild', params: { groupId: this.group._id } });
}
},
},
};
};
</script>

View File

@@ -48,16 +48,15 @@
</template>
<script>
import debounce from 'lodash/debounce';
import debounce from 'lodash/debounce';
import autocomplete from '../chat/autoComplete';
import communityGuidelines from './communityGuidelines';
import chatMessage from '../chat/chatMessages';
import { mapState } from '@/libs/store';
import markdownDirective from '@/directives/markdown';
import autocomplete from '../chat/autoComplete';
import communityGuidelines from './communityGuidelines';
import chatMessage from '../chat/chatMessages';
import { mapState } from '@/libs/store';
import markdownDirective from '@/directives/markdown';
export default {
props: ['label', 'group', 'placeholder'],
export default {
directives: {
markdown: markdownDirective,
},
@@ -66,6 +65,7 @@
communityGuidelines,
chatMessage,
},
props: ['label', 'group', 'placeholder'],
data () {
return {
newMessage: '',
@@ -83,7 +83,7 @@
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
currentLength () {
return this.newMessage.length;
},
@@ -95,11 +95,11 @@
// https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
getCoord (e, text) {
this.caretPosition = text.selectionEnd;
let div = document.createElement('div');
let span = document.createElement('span');
let copyStyle = getComputedStyle(text);
const div = document.createElement('div');
const span = document.createElement('span');
const copyStyle = getComputedStyle(text);
[].forEach.call(copyStyle, (prop) => {
[].forEach.call(copyStyle, prop => {
div.style[prop] = copyStyle[prop];
});
@@ -118,7 +118,7 @@
this._updateCarretPosition(eventUpdate);
}, 250),
_updateCarretPosition (eventUpdate) {
let text = eventUpdate.target;
const text = eventUpdate.target;
this.getCoord(eventUpdate, text);
},
async sendMessageShortcut () {
@@ -150,7 +150,7 @@
// @TODO: I would like to not reload everytime we send. Why are we reloading?
// The response has all the necessary data...
let chat = await this.$store.dispatch('chat:getChat', {groupId: this.group._id});
const chat = await this.$store.dispatch('chat:getChat', { groupId: this.group._id });
this.group.chat = chat;
},
@@ -231,7 +231,7 @@
next();
},
};
};
</script>
<style scoped lang="scss">

View File

@@ -47,14 +47,14 @@ import { mapState } from '@/libs/store';
export default {
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
communityGuidelinesAccepted () {
return this.user.flags.communityGuidelinesAccepted;
},
},
methods: {
acceptCommunityGuidelines () {
this.$store.dispatch('user:set', {'flags.communityGuidelinesAccepted': true});
this.$store.dispatch('user:set', { 'flags.communityGuidelinesAccepted': true });
},
},
};

View File

@@ -140,13 +140,13 @@ b-modal#create-party-modal(size='lg', hide-footer=true)
</style>
<script>
import { mapState } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import notifications from '@/mixins/notifications';
import { mapState } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import notifications from '@/mixins/notifications';
import copyIcon from '@/assets/svg/copy.svg';
import copyIcon from '@/assets/svg/copy.svg';
export default {
export default {
data () {
return {
icons: Object.freeze({
@@ -155,15 +155,15 @@ b-modal#create-party-modal(size='lg', hide-footer=true)
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
async createParty () {
let group = {
const group = {
type: 'party',
};
group.name = this.$t('possessiveParty', {name: this.user.profile.name});
let party = await this.$store.dispatch('guilds:create', {group});
group.name = this.$t('possessiveParty', { name: this.user.profile.name });
const party = await this.$store.dispatch('guilds:create', { group });
this.$store.state.party.data = party;
this.user.party._id = party._id;
@@ -179,7 +179,7 @@ b-modal#create-party-modal(size='lg', hide-footer=true)
if (navigator.clipboard) {
navigator.clipboard.writeText(this.user.auth.local.username);
} else {
let copyText = document.createElement('textarea');
const copyText = document.createElement('textarea');
copyText.value = this.user.auth.local.username;
document.body.appendChild(copyText);
copyText.select();
@@ -190,5 +190,5 @@ b-modal#create-party-modal(size='lg', hide-footer=true)
},
},
mixins: [notifications],
};
};
</script>

View File

@@ -64,7 +64,7 @@ import groupUtilities from '@/mixins/groupsUtilities';
import positiveIcon from '@/assets/svg/positive.svg';
function _mapCategories (guilds) {
guilds.forEach((guild) => {
guilds.forEach(guild => {
if (!guild.categories) return;
guild.categorySlugs = guild.categories.map(cat => {
if (!cat) return;
@@ -74,8 +74,8 @@ function _mapCategories (guilds) {
}
export default {
mixins: [groupUtilities],
components: { PublicGuildItem, MugenScroll, Sidebar },
mixins: [groupUtilities],
data () {
return {
icons: Object.freeze({
@@ -113,14 +113,12 @@ export default {
},
computed: {
filteredGuilds () {
let search = this.search;
let filters = this.filters;
let user = this.$store.state.user.data;
let filterGuild = this.filterGuild;
const { search } = this;
const { filters } = this;
const user = this.$store.state.user.data;
const { filterGuild } = this;
// @TODO: Move this to the server
return this.guilds.filter((guild) => {
return filterGuild(guild, filters, search, user);
});
return this.guilds.filter(guild => filterGuild(guild, filters, search, user));
},
},
methods: {
@@ -133,7 +131,7 @@ export default {
this.queryFilters.search = eventData.searchTerm;
let guilds = await this.$store.dispatch('guilds:getPublicGuilds', this.queryFilters);
const guilds = await this.$store.dispatch('guilds:getPublicGuilds', this.queryFilters);
_mapCategories(guilds);
this.guilds = guilds;
},
@@ -157,7 +155,7 @@ export default {
this.queryFilters.categories = eventData.categories.join(',');
// Role filters
let filteringRole = eventData.roles && eventData.roles.length > 0;
const filteringRole = eventData.roles && eventData.roles.length > 0;
if (filteringRole && eventData.roles.indexOf('member') !== -1) {
this.queryFilters.member = true;
}
@@ -182,7 +180,7 @@ export default {
this.queryFilters.maxMemberCount = 99;
}
let guilds = await this.$store.dispatch('guilds:getPublicGuilds', this.queryFilters);
const guilds = await this.$store.dispatch('guilds:getPublicGuilds', this.queryFilters);
_mapCategories(guilds);
this.guilds = guilds;
},
@@ -194,7 +192,7 @@ export default {
this.loading = true;
this.queryFilters.page = this.lastPageLoaded;
let guilds = await this.$store.dispatch('guilds:getPublicGuilds', this.queryFilters);
const guilds = await this.$store.dispatch('guilds:getPublicGuilds', this.queryFilters);
if (guilds.length === 0) this.hasLoadedAllGuilds = true;
_mapCategories(guilds);

View File

@@ -289,8 +289,6 @@ import silverGuildBadgeIcon from '@/assets/svg/silver-guild-badge-small.svg';
import bronzeGuildBadgeIcon from '@/assets/svg/bronze-guild-badge-small.svg';
export default {
mixins: [groupUtilities, styleHelper],
props: ['groupId'],
components: {
membersModal,
startQuestModal,
@@ -307,6 +305,8 @@ export default {
directives: {
markdown: markdownDirective,
},
mixins: [groupUtilities, styleHelper],
props: ['groupId'],
data () {
return {
searchId: '',
@@ -333,7 +333,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
partyStore () {
return this.$store.state.party;
},
@@ -353,16 +353,6 @@ export default {
return this.group.memberCount > this.$store.state.constants.LARGE_GROUP_COUNT_MESSAGE_CUTOFF;
},
},
mounted () {
if (this.isParty) this.searchId = 'party';
if (!this.searchId) this.searchId = this.groupId;
this.load();
},
beforeRouteUpdate (to, from, next) {
this.$set(this, 'searchId', to.params.groupId);
next();
},
watch: {
// call again the method if the route changes (when this route is already active)
$route: 'fetchGuild',
@@ -375,9 +365,19 @@ export default {
}
},
},
mounted () {
if (this.isParty) this.searchId = 'party';
if (!this.searchId) this.searchId = this.groupId;
this.load();
},
beforeRouteUpdate (to, from, next) {
this.$set(this, 'searchId', to.params.groupId);
next();
},
methods: {
acceptCommunityGuidelines () {
this.$store.dispatch('user:set', {'flags.communityGuidelinesAccepted': true});
this.$store.dispatch('user:set', { 'flags.communityGuidelinesAccepted': true });
},
async load () {
if (this.isParty) {
@@ -393,7 +393,7 @@ export default {
includeAllPublicFields: true,
});
this.$root.$on('updatedGroup', group => {
let updatedGroup = extend(this.group, group);
const updatedGroup = extend(this.group, group);
this.$set(this.group, updatedGroup);
});
},
@@ -442,7 +442,7 @@ export default {
this.group = this.$store.state.party.data;
this.checkForAchievements();
} else {
const group = await this.$store.dispatch('guilds:getGroup', {groupId: this.searchId});
const group = await this.$store.dispatch('guilds:getGroup', { groupId: this.searchId });
this.$set(this, 'group', group);
}
@@ -450,7 +450,7 @@ export default {
if (this.hasUnreadMessages(groupId)) {
// Delay by 1sec to make sure it returns after other requests that don't have the notification marked as read
setTimeout(() => {
this.$store.dispatch('chat:markChatSeen', {groupId});
this.$store.dispatch('chat:markChatSeen', { groupId });
this.$delete(this.user.newMessages, groupId);
}, 1000);
}
@@ -458,9 +458,7 @@ export default {
hasUnreadMessages (groupId) {
if (this.user.newMessages[groupId]) return true;
return this.user.notifications.some(n => {
return n.type === 'NEW_CHAT_MESSAGE' && n.data.group.id === groupId;
});
return this.user.notifications.some(n => n.type === 'NEW_CHAT_MESSAGE' && n.data.group.id === groupId);
},
checkForAchievements () {
// Checks if user's party has reached 2 players for the first time.
@@ -481,7 +479,7 @@ export default {
if (this.group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
return;
}
await this.$store.dispatch('guilds:join', {groupId: this.group._id, type: 'guild'});
await this.$store.dispatch('guilds:join', { groupId: this.group._id, type: 'guild' });
},
clickLeave () {
Analytics.track({
@@ -493,13 +491,13 @@ export default {
// @TODO: Get challenges and ask to keep or remove
if (!confirm('Are you sure you want to leave?')) return;
let keep = true;
const keep = true;
this.leave(keep);
},
async leave (keepTasks) {
let keepChallenges = 'remain-in-challenges';
const keepChallenges = 'remain-in-challenges';
let data = {
const data = {
groupId: this.group._id,
keep: keepTasks,
keepChallenges,
@@ -507,14 +505,14 @@ export default {
if (this.isParty) {
data.type = 'party';
Analytics.updateUser({partySize: null, partyID: null});
Analytics.updateUser({ partySize: null, partyID: null });
this.$store.state.partyMembers = [];
}
await this.$store.dispatch('guilds:leave', data);
if (this.isParty) {
this.$router.push({name: 'tasks'});
this.$router.push({ name: 'tasks' });
}
},
upgradeGroup () {

View File

@@ -185,7 +185,7 @@ export default {
markdown: markdownDirective,
},
data () {
let data = {
const data = {
workingGroup: {
id: '',
name: '',
@@ -267,8 +267,8 @@ export default {
membersToInvite: [],
};
let hashedCategories = {};
data.categoryOptions.forEach((category) => {
const hashedCategories = {};
data.categoryOptions.forEach(category => {
hashedCategories[category.key] = category.label;
});
data.categoriesHashByKey = hashedCategories;
@@ -281,12 +281,12 @@ export default {
return data;
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
editingGroup () {
return this.$store.state.editingGroup;
},
charactersRemaining () {
let currentLength = this.workingGroup.summary ? this.workingGroup.summary.length : 0;
const currentLength = this.workingGroup.summary ? this.workingGroup.summary.length : 0;
return MAX_SUMMARY_SIZE_FOR_GUILDS - currentLength;
},
title () {
@@ -304,7 +304,7 @@ export default {
},
watch: {
editingGroup () {
let editingGroup = this.editingGroup;
const { editingGroup } = this;
if (!editingGroup._id) {
this.resetWorkingGroup();
@@ -339,7 +339,7 @@ export default {
methods: {
async getMembers () {
if (!this.workingGroup.id) return;
let members = await this.$store.dispatch('members:getGroupMembers', {
const members = await this.$store.dispatch('members:getGroupMembers', {
groupId: this.workingGroup.id,
includeAllPublicFields: true,
});
@@ -367,7 +367,7 @@ export default {
// @TODO return $rootScope.openModal('buyGems', {track:"Gems > Gems > Create Group"});
}
let errors = [];
const errors = [];
if (!this.workingGroup.name) errors.push(this.$t('nameRequired'));
if (!this.workingGroup.summary) errors.push(this.$t('summaryRequired'));
@@ -391,10 +391,10 @@ export default {
challenges: this.workingGroup.onlyLeaderCreatesChallenges,
};
let categoryKeys = this.workingGroup.categories;
let serverCategories = [];
const categoryKeys = this.workingGroup.categories;
const serverCategories = [];
categoryKeys.forEach(key => {
let catName = this.categoriesHashByKey[key];
const catName = this.categoriesHashByKey[key];
serverCategories.push({
slug: key,
name: catName,
@@ -402,16 +402,16 @@ export default {
});
this.workingGroup.categories = serverCategories;
let groupData = Object.assign({}, this.workingGroup);
const groupData = { ...this.workingGroup };
let newgroup;
if (groupData.id) {
await this.$store.dispatch('guilds:update', {group: groupData});
await this.$store.dispatch('guilds:update', { group: groupData });
this.$root.$emit('updatedGroup', this.workingGroup);
// @TODO: this doesn't work because of the async resource
// if (updatedGroup.type === 'party') this.$store.state.party = {data: updatedGroup};
} else {
newgroup = await this.$store.dispatch('guilds:create', {group: groupData});
newgroup = await this.$store.dispatch('guilds:create', { group: groupData });
this.$store.state.user.data.balance -= 1;
}

View File

@@ -297,10 +297,10 @@ import creditCardIcon from '@/assets/svg/credit-card-icon.svg';
import amazonButton from '@/components/payments/amazonButton';
export default {
mixins: [paymentsMixin],
components: {
amazonButton,
},
mixins: [paymentsMixin],
data () {
return {
amazonPayments: {},
@@ -341,7 +341,7 @@ export default {
return this.$store.state.upgradingGroup;
},
// @TODO: can we move this to payment mixin?
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
launchModal () {

View File

@@ -90,25 +90,23 @@
</style>
<script>
import { mapState } from '@/libs/store';
import clone from 'lodash/clone';
import debounce from 'lodash/debounce';
import filter from 'lodash/filter';
import forEach from 'lodash/forEach';
import isEmail from 'validator/lib/isEmail';
import isUUID from 'validator/lib/isUUID';
import notifications from '@/mixins/notifications';
import positiveIcon from '@/assets/svg/positive.svg';
import clone from 'lodash/clone';
import debounce from 'lodash/debounce';
import filter from 'lodash/filter';
import forEach from 'lodash/forEach';
import isEmail from 'validator/lib/isEmail';
import isUUID from 'validator/lib/isUUID';
import { mapState } from '@/libs/store';
import notifications from '@/mixins/notifications';
import positiveIcon from '@/assets/svg/positive.svg';
const INVITE_DEFAULTS = {text: '', error: null, valid: null};
const INVITE_DEFAULTS = { text: '', error: null, valid: null };
export default {
export default {
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
cannotSubmit () {
const filteredInvites = filter(this.invites, (invite) => {
return invite.text.length > 0 && !invite.valid;
});
const filteredInvites = filter(this.invites, invite => invite.text.length > 0 && !invite.valid);
if (filteredInvites.length > 0) return true;
return false;
},
@@ -126,26 +124,20 @@
},
methods: {
checkInviteList: debounce(function checkList () {
this.invites = filter(this.invites, (invite, index) => {
return invite.text.length > 0 || index === this.invites.length - 1;
});
this.invites = filter(this.invites, (invite, index) => invite.text.length > 0 || index === this.invites.length - 1);
while (this.invites.length < 2) this.invites.push(clone(INVITE_DEFAULTS));
forEach(this.invites, (value, index) => {
if (value.text.length < 1 || isEmail(value.text)) {
return this.fillErrors(index);
}
if (isUUID(value.text)) {
this.$store.dispatch('user:userLookup', {uuid: value.text})
.then(res => {
return this.fillErrors(index, res);
});
this.$store.dispatch('user:userLookup', { uuid: value.text })
.then(res => this.fillErrors(index, res));
} else {
let searchUsername = value.text;
if (searchUsername[0] === '@') searchUsername = searchUsername.slice(1, searchUsername.length);
this.$store.dispatch('user:userLookup', {username: searchUsername})
.then(res => {
return this.fillErrors(index, res);
});
this.$store.dispatch('user:userLookup', { username: searchUsername })
.then(res => this.fillErrors(index, res));
}
});
}, 250),
@@ -166,16 +158,16 @@
this.$root.$emit('bv::hide::modal', 'invite-modal');
},
async sendInvites () {
let invitationDetails = {
const invitationDetails = {
inviter: this.inviter,
emails: [],
uuids: [],
usernames: [],
};
forEach(this.invites, (invite) => {
forEach(this.invites, invite => {
if (invite.text.length < 1) return;
if (isEmail(invite.text)) {
invitationDetails.emails.push({email: invite.text});
invitationDetails.emails.push({ email: invite.text });
} else if (isUUID(invite.text)) {
invitationDetails.uuids.push(invite.text);
} else {
@@ -188,7 +180,7 @@
});
const invitesSent = invitationDetails.emails.length + invitationDetails.uuids.length + invitationDetails.usernames.length;
let invitationString = invitesSent > 1 ? 'invitationsSent' : 'invitationSent';
const invitationString = invitesSent > 1 ? 'invitationsSent' : 'invitationSent';
this.text(this.$t(invitationString));
this.close();
@@ -196,5 +188,5 @@
},
mixins: [notifications],
props: ['group', 'groupType'],
};
};
</script>

View File

@@ -214,11 +214,11 @@ import starIcon from '@/assets/members/star.svg';
import dots from '@/assets/svg/dots.svg';
export default {
props: ['hideBadge'],
components: {
MemberDetails,
removeMemberModal,
},
props: ['hideBadge'],
data () {
return {
sortOption: {},
@@ -278,7 +278,7 @@ export default {
};
},
mounted () {
this.$root.$on('habitica:show-member-modal', (data) => {
this.$root.$on('habitica:show-member-modal', data => {
// @TODO: Remove store
this.$store.state.memberModalOptions.challengeId = data.challengeId;
this.$store.state.memberModalOptions.groupId = data.groupId;
@@ -294,7 +294,7 @@ export default {
this.$root.$off('habitica:show-member-modal');
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isLeader () {
if (!this.group || !this.group.leader) return false;
return this.user._id === this.group.leader || this.user._id === this.group.leader._id;
@@ -370,10 +370,10 @@ export default {
});
},
async getMembers () {
let groupId = this.groupId;
const { groupId } = this;
if (groupId && groupId !== 'challenge') {
let invites = await this.$store.dispatch('members:getGroupInvites', {
const invites = await this.$store.dispatch('members:getGroupInvites', {
groupId,
includeAllPublicFields: true,
});
@@ -383,7 +383,7 @@ export default {
this.members = this.$store.state.memberModalOptions.viewingMembers;
},
async clickMember (uid, forceShow) {
let user = this.$store.state.user.data;
const user = this.$store.state.user.data;
if (user._id === uid && !forceShow) {
if (this.$route.name === 'tasks') {
@@ -459,7 +459,7 @@ export default {
const lastMember = this.members[this.members.length - 1];
if (!lastMember) return;
let newMembers = await this.$store.state.memberModalOptions.fetchMoreMembers({
const newMembers = await this.$store.state.memberModalOptions.fetchMoreMembers({
challengeId: this.challengeId,
groupId: this.groupId,
lastMemberId: lastMember._id,
@@ -483,10 +483,10 @@ export default {
this.viewMembers();
},
async promoteToLeader (member) {
let groupData = Object.assign({}, this.group);
const groupData = { ...this.group };
groupData.leader = member._id;
await this.$store.dispatch('guilds:update', {group: groupData});
await this.$store.dispatch('guilds:update', { group: groupData });
alert(this.$t('leaderChanged'));

View File

@@ -61,10 +61,10 @@
</style>
<script>
import MugenScroll from 'vue-mugen-scroll';
import { mapState } from '@/libs/store';
import groupUtilities from '@/mixins/groupsUtilities';
import MugenScroll from 'vue-mugen-scroll';
import PublicGuildItem from './publicGuildItem';
import Sidebar from './sidebar';
@@ -73,8 +73,8 @@ import greyBadgeIcon from '@/assets/svg/grey-badge.svg';
import positiveIcon from '@/assets/svg/positive.svg';
export default {
mixins: [groupUtilities],
components: { PublicGuildItem, MugenScroll, Sidebar },
mixins: [groupUtilities],
data () {
return {
icons: Object.freeze({
@@ -109,15 +109,13 @@ export default {
guilds: 'myGuilds',
}),
filteredGuilds () {
let search = this.search;
let filters = this.filters;
let user = this.$store.state.user.data;
let filterGuild = this.filterGuild;
return this.guilds.filter((guild) => {
const { search } = this;
const { filters } = this;
const user = this.$store.state.user.data;
const { filterGuild } = this;
return this.guilds.filter(guild => {
if (guild.categories) {
guild.categorySlugs = guild.categories.map(cat => {
return cat.slug;
});
guild.categorySlugs = guild.categories.map(cat => cat.slug);
}
return filterGuild(guild, filters, search, user);
});

View File

@@ -71,16 +71,16 @@ import { mapGetters } from '@/libs/store';
import MemberDetails from '../memberDetails';
export default {
props: ['group'],
components: {
MemberDetails,
},
props: ['group'],
computed: {
...mapGetters({
partyMembers: 'party:members',
}),
participants () {
let partyMembers = this.partyMembers || [];
const partyMembers = this.partyMembers || [];
return partyMembers.filter(member => this.group.quest.members[member._id] === true);
},
},

View File

@@ -144,16 +144,16 @@ import bronzeGuildBadgeIcon from '@/assets/svg/bronze-guild-badge-large.svg';
import { MAX_SUMMARY_SIZE_FOR_GUILDS } from '@/../../common/script/constants';
export default {
mixins: [groupUtilities],
directives: {
markdown,
},
props: ['guild', 'displayLeave', 'displayGemBank'],
components: {
categoryTags,
},
mixins: [groupUtilities],
props: ['guild', 'displayLeave', 'displayGemBank'],
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isOwner () {
return this.guild.leader && this.guild.leader === this.user._id;
},
@@ -174,9 +174,9 @@ export default {
},
methods: {
showSuggested (guildId) {
let habiticaHelpingGuildId = '5481ccf3-5d2d-48a9-a871-70a7380cee5a';
let sixtyDaysAgoFromNow = moment().subtract(60, 'days');
let isUserNew = moment(this.user.auth.timestamps.created).isAfter(sixtyDaysAgoFromNow);
const habiticaHelpingGuildId = '5481ccf3-5d2d-48a9-a871-70a7380cee5a';
const sixtyDaysAgoFromNow = moment().subtract(60, 'days');
const isUserNew = moment(this.user.auth.timestamps.created).isAfter(sixtyDaysAgoFromNow);
return guildId === habiticaHelpingGuildId && isUserNew;
},
async join () {
@@ -184,11 +184,11 @@ export default {
if (this.guild.cancelledPlan && !confirm(window.env.t('aboutToJoinCancelledGroupPlan'))) {
return;
}
await this.$store.dispatch('guilds:join', {groupId: this.guild._id, type: 'guild'});
await this.$store.dispatch('guilds:join', { groupId: this.guild._id, type: 'guild' });
},
async leave () {
// @TODO: ask about challenges when we add challenges
await this.$store.dispatch('guilds:leave', {groupId: this.guild._id, type: 'myGuilds'});
await this.$store.dispatch('guilds:leave', { groupId: this.guild._id, type: 'myGuilds' });
},
},
};

View File

@@ -149,11 +149,11 @@ import questDialogDrops from '../shops/quests/questDialogDrops';
import questDialogContent from '../shops/quests/questDialogContent';
export default {
props: ['group'],
components: {
questDialogDrops,
questDialogContent,
},
props: ['group'],
data () {
return {
loading: false,
@@ -181,38 +181,36 @@ export default {
return quests.quests[this.group.quest.key];
},
members () {
let partyMembers = this.partyMembers || [];
return partyMembers.map(member => {
return {
const partyMembers = this.partyMembers || [];
return partyMembers.map(member => ({
name: member.profile.name,
accepted: this.group.quest.members[member._id],
};
});
}));
},
canEditQuest () {
if (!this.group.quest) return false;
let isQuestLeader = this.group.quest.leader === this.user._id;
let isPartyLeader = this.group.leader._id === this.user._id;
const isQuestLeader = this.group.quest.leader === this.user._id;
const isPartyLeader = this.group.leader._id === this.user._id;
return isQuestLeader || isPartyLeader;
},
},
methods: {
async questConfirm () {
let count = 0;
for (let uuid in this.group.quest.members) {
for (const uuid in this.group.quest.members) {
if (this.group.quest.members[uuid]) count += 1;
}
if (!confirm(this.$t('questConfirm', { questmembers: count, totalmembers: this.group.memberCount}))) return;
if (!confirm(this.$t('questConfirm', { questmembers: count, totalmembers: this.group.memberCount }))) return;
this.questForceStart();
},
async questForceStart () {
let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/force-start'});
const quest = await this.$store.dispatch('quests:sendAction', { groupId: this.group._id, action: 'quests/force-start' });
this.group.quest = quest;
this.close();
},
async questCancel () {
if (!confirm(this.$t('sureCancel'))) return;
let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/cancel'});
const quest = await this.$store.dispatch('quests:sendAction', { groupId: this.group._id, action: 'quests/cancel' });
this.group.quest = quest;
this.close();
},

View File

@@ -198,10 +198,10 @@ import sidebarSection from '../sidebarSection';
import questIcon from '@/assets/svg/quest.svg';
export default {
props: ['group'],
components: {
sidebarSection,
},
props: ['group'],
data () {
return {
icons: Object.freeze({
@@ -210,7 +210,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
userIsOnQuest () {
if (!this.group.quest || !this.group.quest.members) return false;
return Boolean(this.group.quest.members[this.user._id]);
@@ -230,20 +230,20 @@ export default {
},
canEditQuest () {
if (!this.group.quest) return false;
let isQuestLeader = this.group.quest.leader === this.user._id;
let isPartyLeader = this.group.leader._id === this.user._id;
const isQuestLeader = this.group.quest.leader === this.user._id;
const isPartyLeader = this.group.leader._id === this.user._id;
return isQuestLeader || isPartyLeader;
},
isMemberOfPendingQuest () {
let userid = this.user._id;
let group = this.group;
const userid = this.user._id;
const { group } = this;
if (!group.quest || !group.quest.members) return false;
if (group.quest.active) return false; // quest is started, not pending
return userid in group.quest.members && group.quest.members[userid] !== false;
},
isMemberOfRunningQuest () {
let userid = this.user._id;
let group = this.group;
const userid = this.user._id;
const { group } = this;
if (!group.quest || !group.quest.members) return false;
if (!group.quest.active) return false; // quest is pending, not started
return group.quest.members[userid];
@@ -253,7 +253,7 @@ export default {
if (!this.group || !this.group.quest) return count;
for (let uuid in this.group.quest.members) {
for (const uuid in this.group.quest.members) {
if (this.group.quest.members[uuid]) count += 1;
}
@@ -273,20 +273,20 @@ export default {
async questAbort () {
if (!confirm(this.$t('sureAbort'))) return;
if (!confirm(this.$t('doubleSureAbort'))) return;
let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/abort'});
const quest = await this.$store.dispatch('quests:sendAction', { groupId: this.group._id, action: 'quests/abort' });
this.group.quest = quest;
},
async questLeave () {
if (!confirm(this.$t('sureLeave'))) return;
let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/leave'});
const quest = await this.$store.dispatch('quests:sendAction', { groupId: this.group._id, action: 'quests/leave' });
this.group.quest = quest;
},
async questAccept (partyId) {
let quest = await this.$store.dispatch('quests:sendAction', {groupId: partyId, action: 'quests/accept'});
const quest = await this.$store.dispatch('quests:sendAction', { groupId: partyId, action: 'quests/accept' });
this.user.party.quest = quest;
},
async questReject (partyId) {
let quest = await this.$store.dispatch('quests:sendAction', {groupId: partyId, action: 'quests/reject'});
const quest = await this.$store.dispatch('quests:sendAction', { groupId: partyId, action: 'quests/reject' });
this.user.party.quest = quest;
},
},

View File

@@ -123,12 +123,12 @@ import questDialogContent from '../shops/quests/questDialogContent';
import QuestInfo from '../shops/quests/questInfo';
export default {
props: ['group'],
components: {
questDialogDrops,
questDialogContent,
QuestInfo,
},
props: ['group'],
data () {
return {
loading: false,
@@ -162,7 +162,7 @@ export default {
this.$root.$off('selectQuest', this.selectQuest);
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
questData () {
return quests.quests[this.selectedQuest];
},
@@ -179,11 +179,11 @@ export default {
partySize: this.group.memberCount,
});
let groupId = this.group._id || this.user.party._id;
const groupId = this.group._id || this.user.party._id;
const key = this.selectedQuest;
try {
const response = await this.$store.dispatch('guilds:inviteToQuest', {groupId, key});
const response = await this.$store.dispatch('guilds:inviteToQuest', { groupId, key });
const quest = response.data.data;
if (this.$store.state.party.data) this.$store.state.party.data.quest = quest;

View File

@@ -501,14 +501,14 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
questData () {
if (!this.group.quest) return {};
return quests.quests[this.group.quest.key];
},
},
async mounted () {
this.group = await this.$store.dispatch('guilds:getGroup', {groupId: TAVERN_ID});
this.group = await this.$store.dispatch('guilds:getGroup', { groupId: TAVERN_ID });
},
methods: {
modForm () {
@@ -543,7 +543,7 @@ export default {
}
},
async fetchRecentMessages () {
this.group = await this.$store.dispatch('guilds:getGroup', {groupId: TAVERN_ID});
this.group = await this.$store.dispatch('guilds:getGroup', { groupId: TAVERN_ID });
},
},
};

View File

@@ -119,10 +119,13 @@ import notifications from '@/mixins/notifications';
import userLink from '../userLink';
export default {
mixins: [notifications, styleHelper],
components: {
userLink,
},
directives: {
markdown: markdownDirective,
},
mixins: [notifications, styleHelper],
data () {
return {
heroes: [],
@@ -141,14 +144,11 @@ export default {
expandAuth: false,
};
},
directives: {
markdown: markdownDirective,
},
async mounted () {
this.heroes = await this.$store.dispatch('hall:getHeroes');
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
getAllItemPaths () {
@@ -172,7 +172,7 @@ export default {
getFormattedItemReference (pathPrefix, itemKeys, values) {
let finishedString = '\n'.concat('path: ', pathPrefix, ', ', 'value: {', values, '}\n');
each(itemKeys, (key) => {
each(itemKeys, key => {
finishedString = finishedString.concat('\t', pathPrefix, '.', key, '\n');
});
@@ -180,8 +180,8 @@ export default {
},
async loadHero (uuid, heroIndex) {
this.currentHeroIndex = heroIndex;
let hero = await this.$store.dispatch('hall:getHero', { uuid });
this.hero = Object.assign({}, hero);
const hero = await this.$store.dispatch('hall:getHero', { uuid });
this.hero = { ...hero };
if (!this.hero.flags) {
this.hero.flags = {
chatRevoked: false,
@@ -192,8 +192,8 @@ export default {
this.expandAuth = false;
},
async saveHero () {
this.hero.contributor.admin = this.hero.contributor.level > 7 ? true : false;
let heroUpdated = await this.$store.dispatch('hall:updateHero', { heroDetails: this.hero });
this.hero.contributor.admin = this.hero.contributor.level > 7;
const heroUpdated = await this.$store.dispatch('hall:updateHero', { heroDetails: this.hero });
this.text('User updated');
this.hero = {};
this.heroID = -1;

View File

@@ -32,7 +32,7 @@ export default {
this.patrons = await this.$store.dispatch('hall:getPatrons', { page: 0 });
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
},
methods: {
// @TODO: Import member modal - clickMember()

View File

@@ -178,7 +178,7 @@ export default {
}
},
mounted () {
this.$root.$on('inviteModal::inviteToGroup', (group) => {
this.$root.$on('inviteModal::inviteToGroup', group => {
this.inviteModalGroup = group;
this.inviteModalGroupType = group.type === 'guild' ? 'Guild' : 'Party';
this.$root.$emit('bv::show::modal', 'invite-modal');

View File

@@ -488,7 +488,7 @@ export default {
eventLabel: 'Gems > Toolbar',
});
this.$root.$emit('bv::show::modal', 'buy-gems', {alreadyTracked: true});
this.$root.$emit('bv::show::modal', 'buy-gems', { alreadyTracked: true });
},
dropdownDesktop (hover) {
if (this.isDesktop() && hover.target.classList.contains('droppable')) {
@@ -499,7 +499,7 @@ export default {
this.dropdown(click.currentTarget.parentElement);
},
dropdown (element) {
let droppedElement = document.getElementsByClassName('down')[0];
const droppedElement = document.getElementsByClassName('down')[0];
if (droppedElement && droppedElement !== element) {
droppedElement.classList.remove('down');
if (droppedElement.lastChild) {

View File

@@ -130,7 +130,7 @@ export default {
};
},
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isNotBailey () {
return this.notification.type !== 'NEW_STUFF';
},
@@ -141,7 +141,7 @@ export default {
}),
clicked () {
if (this.readAfterClick === true) {
this.readNotification({notificationId: this.notification.id});
this.readNotification({ notificationId: this.notification.id });
}
this.$emit('click');
@@ -149,12 +149,12 @@ export default {
remove () {
if (this.notification.type === 'NEW_CHAT_MESSAGE') {
const groupId = this.notification.data.group.id;
this.$store.dispatch('chat:markChatSeen', {groupId});
this.$store.dispatch('chat:markChatSeen', { groupId });
if (this.user.newMessages[groupId]) {
this.$delete(this.user.newMessages, groupId);
}
} else {
this.readNotification({notificationId: this.notification.id});
this.readNotification({ notificationId: this.notification.id });
}
},
},

View File

@@ -14,10 +14,10 @@ base-notification(
import BaseNotification from './base';
export default {
props: ['notification', 'canRemove'],
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
computed: {
cardString () {
return this.$t(`${this.notification.data.card}Card`);
@@ -28,7 +28,7 @@ export default {
},
methods: {
action () {
this.$router.push({name: 'items'});
this.$router.push({ name: 'items' });
},
},
};

View File

@@ -18,13 +18,13 @@ import { mapState } from '@/libs/store';
import sync from '@/mixins/sync';
export default {
mixins: [sync],
props: ['notification', 'canRemove'],
components: {
BaseNotification,
},
mixins: [sync],
props: ['notification', 'canRemove'],
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
// Check that the notification has all the necessary data (old ones are missing some fields)
notificationHasData () {
return Boolean(this.notification.data.groupTaskId && this.notification.data.userId);
@@ -33,14 +33,17 @@ export default {
methods: {
action () {
const groupId = this.notification.data.group.id;
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId }});
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId } });
},
async approve () {
// Redirect users to the group tasks page if the notification doesn't have data
if (!this.notificationHasData) {
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: {
this.$router.push({
name: 'groupPlanDetailTaskInformation',
params: {
groupId: this.notification.data.groupId,
}});
},
});
return;
}
@@ -55,9 +58,12 @@ export default {
async needsWork () {
// Redirect users to the group tasks page if the notification doesn't have data
if (!this.notificationHasData) {
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: {
this.$router.push({
name: 'groupPlanDetailTaskInformation',
params: {
groupId: this.notification.data.groupId,
}});
},
});
return;
}

View File

@@ -13,14 +13,14 @@ base-notification(
import BaseNotification from './base';
export default {
props: ['notification', 'canRemove'],
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
methods: {
action () {
const groupId = this.notification.data.groupId;
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId }});
const { groupId } = this.notification.data;
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId } });
},
},
};

View File

@@ -10,17 +10,17 @@
</template>
<script>
import BaseNotification from './base';
import BaseNotification from './base';
export default {
props: ['notification', 'canRemove'],
export default {
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
methods: {
action () {
this.$router.push({ name: 'tasks'});
this.$router.push({ name: 'tasks' });
},
},
};
};
</script>

View File

@@ -13,14 +13,14 @@ base-notification(
import BaseNotification from './base';
export default {
props: ['notification', 'canRemove'],
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
methods: {
action () {
const groupId = this.notification.data.groupId;
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId }});
const { groupId } = this.notification.data;
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId } });
},
},
};

View File

@@ -13,14 +13,14 @@ base-notification(
import BaseNotification from './base';
export default {
props: ['notification', 'canRemove'],
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
methods: {
action () {
const groupId = this.notification.data.group.id;
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId }});
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId } });
},
},
};

View File

@@ -17,12 +17,12 @@ import BaseNotification from './base';
import { mapState } from '@/libs/store';
export default {
props: ['notification', 'canRemove'],
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
computed: {
...mapState({user: 'user.data'}),
...mapState({ user: 'user.data' }),
isPublicGuild () {
if (this.notification.data.publicGuild === true) return true;
return false;
@@ -31,10 +31,9 @@ export default {
const guild = this.notification.data.name;
if (this.isPublicGuild) {
return this.$t('invitedToPublicGuild', {guild});
} else {
return this.$t('invitedToPrivateGuild', {guild});
return this.$t('invitedToPublicGuild', { guild });
}
return this.$t('invitedToPrivateGuild', { guild });
},
},
methods: {
@@ -52,11 +51,11 @@ export default {
return;
}
await this.$store.dispatch('guilds:join', {groupId: group.id, type: 'guild'});
await this.$store.dispatch('guilds:join', { groupId: group.id, type: 'guild' });
this.$router.push({ name: 'guild', params: { groupId: group.id } });
},
reject () {
this.$store.dispatch('guilds:rejectInvite', {groupId: this.notification.data.id, type: 'guild'});
this.$store.dispatch('guilds:rejectInvite', { groupId: this.notification.data.id, type: 'guild' });
},
},

View File

@@ -9,13 +9,13 @@
</template>
<script>
import BaseNotification from './base';
import BaseNotification from './base';
export default {
props: ['notification', 'canRemove'],
export default {
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
computed: {
achievementString () {
return `<strong>${this.$t('achievement')}</strong>: ${this.$t('achievementJustAddWater')}`;
@@ -26,5 +26,5 @@
this.$root.$emit('bv::show::modal', 'just-add-water');
},
},
};
};
</script>

Some files were not shown because too many files have changed in this diff Show More