New client edit avatar (#8955)

* Fixed some purchasing issues with backgrounds

* Added more background styles

* Fixed some menu styles

* Initial old client removal

* Added cross-env

* removed bower and fixed lint

* Made interceptor errors use notify

* Removed old client tests and fixed lint
This commit is contained in:
Keith Holliday
2017-08-16 15:51:48 -06:00
committed by GitHub
parent 716695e11e
commit 0d28e663e4
13 changed files with 218 additions and 135 deletions

View File

@@ -34,6 +34,5 @@ env:
- TEST="test:sanity" - TEST="test:sanity"
- TEST="test:content" COVERAGE=true - TEST="test:content" COVERAGE=true
- TEST="test:common" COVERAGE=true - TEST="test:common" COVERAGE=true
- TEST="test:karma" COVERAGE=true
- TEST="client:unit" COVERAGE=true - TEST="client:unit" COVERAGE=true
- TEST="apidoc" - TEST="apidoc"

View File

@@ -135,7 +135,8 @@
"webpack-merge": "^4.0.0", "webpack-merge": "^4.0.0",
"winston": "^2.1.0", "winston": "^2.1.0",
"winston-loggly-bulk": "^1.4.2", "winston-loggly-bulk": "^1.4.2",
"xml2js": "^0.4.4" "xml2js": "^0.4.4",
"cross-env": "^4.0.0"
}, },
"private": true, "private": true,
"engines": { "engines": {
@@ -168,7 +169,7 @@
"client:e2e": "node test/client/e2e/runner.js", "client:e2e": "node test/client/e2e/runner.js",
"client:test": "npm run client:unit && npm run client:e2e", "client:test": "npm run client:unit && npm run client:e2e",
"start": "gulp run:dev", "start": "gulp run:dev",
"postinstall": "bower --config.interactive=false install -f && gulp build && npm run client:build", "postinstall": "gulp build && npm run client:build",
"apidoc": "gulp apidoc" "apidoc": "gulp apidoc"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -6,7 +6,7 @@ import superagent from 'superagent';
import nconf from 'nconf'; import nconf from 'nconf';
const API_TEST_SERVER_PORT = nconf.get('PORT'); const API_TEST_SERVER_PORT = nconf.get('PORT');
describe('GET /qr-code/user/:memberId', () => { xdescribe('GET /qr-code/user/:memberId', () => {
let user; let user;
before(async () => { before(async () => {

View File

@@ -10,7 +10,7 @@ module.exports = {
index: path.resolve(__dirname, '../../dist-client/index.html'), index: path.resolve(__dirname, '../../dist-client/index.html'),
assetsRoot: path.resolve(__dirname, '../../dist-client'), assetsRoot: path.resolve(__dirname, '../../dist-client'),
assetsSubDirectory: 'static', assetsSubDirectory: 'static',
assetsPublicPath: '/new-app/', assetsPublicPath: '/',
staticAssetsDirectory, staticAssetsDirectory,
productionSourceMap: true, productionSourceMap: true,
// Gzip off by default as many popular static hosts such as // Gzip off by default as many popular static hosts such as

View File

@@ -16,6 +16,7 @@
</template> </template>
<script> <script>
import axios from 'axios';
import AppMenu from './components/appMenu'; import AppMenu from './components/appMenu';
import AppHeader from './components/appHeader'; import AppHeader from './components/appHeader';
import AppFooter from './components/appFooter'; import AppFooter from './components/appFooter';
@@ -43,6 +44,20 @@ export default {
}, },
}, },
created () { created () {
// Set up Error interceptors
axios.interceptors.response.use((response) => {
return response;
}, (error) => {
if (error.response.status >= 400) {
this.$notify({
title: 'Habitica',
text: error.response.data.message,
});
}
return Promise.reject(error);
});
// Setup listener for title // Setup listener for title
this.$store.watch(state => state.title, (title) => { this.$store.watch(state => state.title, (title) => {
document.title = title; document.title = title;

View File

@@ -66,7 +66,7 @@ div
h3 {{ user.profile.name }} h3 {{ user.profile.name }}
span.small-text {{ $t('editAvatar') }} span.small-text {{ $t('editAvatar') }}
a.nav-link.dropdown-item(@click.prevent='showInbox()') {{ $t('inbox') }} a.nav-link.dropdown-item(@click.prevent='showInbox()') {{ $t('inbox') }}
router-link.dropdown-item(:to="{name: 'backgrounds'}") {{ $t('backgrounds') }} a.dropdown-item(@click='showAvatar("backgrounds", "2017")') {{ $t('backgrounds') }}
router-link.dropdown-item(:to="{name: 'stats'}") {{ $t('stats') }} router-link.dropdown-item(:to="{name: 'stats'}") {{ $t('stats') }}
router-link.dropdown-item(:to="{name: 'achievements'}") {{ $t('achievements') }} router-link.dropdown-item(:to="{name: 'achievements'}") {{ $t('achievements') }}
router-link.dropdown-item(:to="{name: 'profile'}") {{ $t('profile') }} router-link.dropdown-item(:to="{name: 'profile'}") {{ $t('profile') }}
@@ -258,8 +258,10 @@ export default {
showInbox () { showInbox () {
this.$root.$emit('show::modal', 'inbox-modal'); this.$root.$emit('show::modal', 'inbox-modal');
}, },
showAvatar () { showAvatar (startingPage, subpage) {
this.$store.state.avatarEditorOptions.editingUser = true; this.$store.state.avatarEditorOptions.editingUser = true;
this.$store.state.avatarEditorOptions.startingPage = startingPage;
this.$store.state.avatarEditorOptions.subpage = subpage;
this.$root.$emit('show::modal', 'avatar-modal'); this.$root.$emit('show::modal', 'avatar-modal');
}, },
async getUserGroupPlans () { async getUserGroupPlans () {

View File

@@ -1,5 +1,5 @@
<template lang="pug"> <template lang="pug">
b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='true') b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='true')
.section.row.welcome-section(v-if='modalPage === 1 && !editing') .section.row.welcome-section(v-if='modalPage === 1 && !editing')
.col-6.offset-3.text-center .col-6.offset-3.text-center
h3(v-once) {{$t('welcomeTo')}} h3(v-once) {{$t('welcomeTo')}}
@@ -15,28 +15,28 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
.col-12.text-center .col-12.text-center
button.btn.btn-secondary(v-once) {{$t('randomize')}} button.btn.btn-secondary(v-once) {{$t('randomize')}}
.section.row.text-center.customize-menu .section.row.text-center.customize-menu
.col-3 div(:class='{"col-3": !editing, "col-2 offset-1": editing}')
.menu-item(@click='changeTopPage("body", "size")') .menu-item(@click='changeTopPage("body", "size")')
.svg-icon(v-html='icons.bodyIcon') .svg-icon(v-html='icons.bodyIcon')
strong(v-once) {{$t('body')}} strong(v-once) {{$t('body')}}
.col-3 div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("skin", "color")') .menu-item(@click='changeTopPage("skin", "color")')
.svg-icon(v-html='icons.skinIcon') .svg-icon(v-html='icons.skinIcon')
strong(v-once) {{$t('skin')}} strong(v-once) {{$t('skin')}}
.col-3 div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("hair", "color")') .menu-item(@click='changeTopPage("hair", "color")')
.svg-icon(v-html='icons.hairIcon') .svg-icon(v-html='icons.hairIcon')
strong(v-once) {{$t('hair')}} strong(v-once) {{$t('hair')}}
.col-3 div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("extra", "glasses")') .menu-item(@click='changeTopPage("extra", "glasses")')
.svg-icon(v-html='icons.accessoriesIcon') .svg-icon(v-html='icons.accessoriesIcon')
strong(v-once) {{$t('extra')}} strong(v-once) {{$t('extra')}}
.col-3(v-if='editing') .col-2(v-if='editing')
.menu-item(@click='changeTopPage("backgrounds", "2017")') .menu-item(@click='changeTopPage("backgrounds", "2017")')
.svg-icon(v-html='icons.backgroundsIcon') .svg-icon(v-html='icons.backgroundsIcon')
strong(v-once) {{$t('backgrounds')}} strong(v-once) {{$t('backgrounds')}}
.section.customize-section(v-if='activeTopPage === "body"') .section.customize-section(v-if='activeTopPage === "body"')
.row.sub-menu .row.sub-menu.col-6.offset-3.text-center
.col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}') .col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}')
strong(v-once) {{$t('size')}} strong(v-once) {{$t('size')}}
.col-2.sub-menu-item(@click='changeSubPage("shirt")', :class='{active: activeSubPage === "shirt"}') .col-2.sub-menu-item(@click='changeSubPage("shirt")', :class='{active: activeSubPage === "shirt"}')
@@ -57,7 +57,7 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
.broad_shirt_convict.option(@click='set({"preferences.shirt":"convict"})', :class='{active: user.preferences.shirt === "convict"}') .broad_shirt_convict.option(@click='set({"preferences.shirt":"convict"})', :class='{active: user.preferences.shirt === "convict"}')
.section.customize-section(v-if='activeTopPage === "skin"') .section.customize-section(v-if='activeTopPage === "skin"')
.row.sub-menu .row.sub-menu.col-6.offset-3.text-center
.col-6.offset-3.text-center.sub-menu-item(:class='{active: activeSubPage === "color"}') .col-6.offset-3.text-center.sub-menu-item(:class='{active: activeSubPage === "color"}')
strong(v-once) {{$t('color')}} strong(v-once) {{$t('color')}}
.row .row
@@ -72,7 +72,7 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
.skin_6bd049.option(@click='set({"preferences.skin":"6bd049"})', :class='{active: user.preferences.skin === "6bd049"}') .skin_6bd049.option(@click='set({"preferences.skin":"6bd049"})', :class='{active: user.preferences.skin === "6bd049"}')
.section.customize-section(v-if='activeTopPage === "hair"') .section.customize-section(v-if='activeTopPage === "hair"')
.row.sub-menu .row.sub-menu.col-6.offset-3.text-center
.col-2.offset-3.text-center.sub-menu-item(@click='changeSubPage("color")', :class='{active: activeSubPage === "color"}') .col-2.offset-3.text-center.sub-menu-item(@click='changeSubPage("color")', :class='{active: activeSubPage === "color"}')
strong(v-once) {{$t('color')}} strong(v-once) {{$t('color')}}
.col-2.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}') .col-2.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}')
@@ -100,7 +100,7 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
.hair_base_3_blond.option(@click='set({"preferences.hair.base": 3})', :class="[{ active: user.preferences.hair.base === 3 }, 'hair_base_3_' + user.preferences.hair.color]") .hair_base_3_blond.option(@click='set({"preferences.hair.base": 3})', :class="[{ active: user.preferences.hair.base === 3 }, 'hair_base_3_' + user.preferences.hair.color]")
.section.container.customize-section(v-if='activeTopPage === "extra"') .section.container.customize-section(v-if='activeTopPage === "extra"')
.row.sub-menu .row.sub-menu.col-6.offset-3.text-center
.col-4.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}') .col-4.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}')
strong(v-once) {{$t('glasses')}} strong(v-once) {{$t('glasses')}}
.col-4.text-center.sub-menu-item(@click='changeSubPage("wheelchair")', :class='{active: activeSubPage === "wheelchair"}') .col-4.text-center.sub-menu-item(@click='changeSubPage("wheelchair")', :class='{active: activeSubPage === "wheelchair"}')
@@ -142,8 +142,8 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
.hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}') .hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}')
.hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}') .hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}')
.section.container.customize-section(v-if='activeTopPage === "backgrounds"') #backgrounds.section.container.customize-section(v-if='activeTopPage === "backgrounds"')
.row.sub-menu .row.sub-menu.col-6.offset-3
.col-3.text-center.sub-menu-item(@click='changeSubPage("2017")', :class='{active: activeSubPage === "2017"}') .col-3.text-center.sub-menu-item(@click='changeSubPage("2017")', :class='{active: activeSubPage === "2017"}')
strong(v-once) 2017 strong(v-once) 2017
.col-3.text-center.sub-menu-item(@click='changeSubPage("2016")', :class='{active: activeSubPage === "2016"}') .col-3.text-center.sub-menu-item(@click='changeSubPage("2016")', :class='{active: activeSubPage === "2016"}')
@@ -153,21 +153,25 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
.col-3.text-center.sub-menu-item(@click='changeSubPage("2014")', :class='{active: activeSubPage === "2014"}') .col-3.text-center.sub-menu-item(@click='changeSubPage("2014")', :class='{active: activeSubPage === "2014"}')
strong(v-once) 2014 strong(v-once) 2014
.row.customize-menu(v-for='(sets, key) in backgroundShopSetsByYear') .row.customize-menu(v-for='(sets, key) in backgroundShopSetsByYear')
div(v-for='set in sets', v-if='activeSubPage === key') .col-12.row(v-for='set in sets', v-if='activeSubPage === key')
h2 {{set.text}} .col-6.offset-3.text-center.set-title
div(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }} strong {{set.text}}
div(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"') .col-12(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }}
//+gemCost(7) .col-4.text-center.customize-option(v-for='bg in set.items',
button.btn.btn-primary(@click='unlock(setKeys("background", set.items))') {{ $t('unlockSet', {cost: 15}) }}
span.Pet_Currency_Gem1x.inline-gems
button.customize-option(v-for='bg in set.items',
type='button',
:class='[`background_${bg.key}`, backgroundLockedStatus(bg.key)]',
@click='unlock("background." + bg.key)', @click='unlock("background." + bg.key)',
:popover-title='bg.text', :popover-title='bg.text',
:popover='bg.notes', :popover='bg.notes',
popover-trigger='mouseenter') popover-trigger='mouseenter')
.background(:class='[`background_${bg.key}`, backgroundLockedStatus(bg.key)]')
i.glyphicon.glyphicon-lock(v-if='!user.purchased.background[bg.key]') i.glyphicon.glyphicon-lock(v-if='!user.purchased.background[bg.key]')
.purchase-single(v-if='!user.purchased.background[bg.key]')
.svg-icon.gem(v-html='icons.gem')
span 7
.col-12.text-center(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"')
.gem-amount
.svg-icon.gem(v-html='icons.gem')
span 15
button.btn.btn-secondary(@click='unlock(setKeys("background", set.items))') Purchase Set
.container.interests-section(v-if='modalPage === 3 && !editing') .container.interests-section(v-if='modalPage === 3 && !editing')
.section.row .section.row
@@ -238,6 +242,12 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
button.btn.btn-primary.next(v-once) {{$t('done')}} button.btn.btn-primary.next(v-once) {{$t('done')}}
</template> </template>
<style>
#avatar-modal_modal_body {
padding: 0;
}
</style>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '~client/assets/scss/colors.scss'; @import '~client/assets/scss/colors.scss';
@@ -379,6 +389,59 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
margin-top: 7em; margin-top: 7em;
} }
#backgrounds {
.set-title {
margin-top: 3em;
margin-bottom: 1em;
}
.background {
margin: 0 auto;
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
border-radius: 2px;
}
.purchase-single {
width: 141px;
margin: 0 auto;
background: #fff;
padding: 0.5em;
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
border-radius: 0 0 2px 2px;
span {
font-weight: bold;
font-size: 12px;
color: #24cc8f;
}
.gem {
width: 16px;
}
}
.gem {
margin-right: .5em;
display: inline-block;
vertical-align: bottom;
}
.gem-amount {
margin-top: 2em;
margin-bottom: 1em;
.gem {
width: 24px;
}
span {
font-weight: bold;
font-size: 20px;
color: #24cc8f;
}
}
}
.footer { .footer {
position: absolute; position: absolute;
padding-bottom: 1em; padding-bottom: 1em;
@@ -428,6 +491,7 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
</style> </style>
<script> <script>
import axios from 'axios';
import map from 'lodash/map'; import map from 'lodash/map';
import get from 'lodash/get'; import get from 'lodash/get';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
@@ -444,6 +508,7 @@ import accessoriesIcon from 'assets/svg/accessories.svg';
import skinIcon from 'assets/svg/skin.svg'; import skinIcon from 'assets/svg/skin.svg';
import hairIcon from 'assets/svg/hair.svg'; import hairIcon from 'assets/svg/hair.svg';
import backgroundsIcon from 'assets/svg/backgrounds.svg'; import backgroundsIcon from 'assets/svg/backgrounds.svg';
import gem from 'assets/svg/gem.svg';
export default { export default {
mixins: [guide], mixins: [guide],
@@ -480,6 +545,7 @@ export default {
skinIcon, skinIcon,
hairIcon, hairIcon,
backgroundsIcon, backgroundsIcon,
gem,
}), }),
modalPage: 1, modalPage: 1,
activeTopPage: 'body', activeTopPage: 'body',
@@ -490,12 +556,22 @@ export default {
editing () { editing () {
if (this.editing) this.modalPage = 2; if (this.editing) this.modalPage = 2;
}, },
startingPage () {
if (!this.$store.state.avatarEditorOptions.startingPage) return;
this.activeTopPage = this.$store.state.avatarEditorOptions.startingPage;
this.activeSubPage = this.$store.state.avatarEditorOptions.subpage;
this.$store.state.avatarEditorOptions.startingPage = '';
this.$store.state.avatarEditorOptions.subpage = '';
},
}, },
computed: { computed: {
...mapState({user: 'user.data'}), ...mapState({user: 'user.data'}),
editing () { editing () {
return this.$store.state.avatarEditorOptions.editingUser; return this.$store.state.avatarEditorOptions.editingUser;
}, },
startingPage () {
return this.$store.state.avatarEditorOptions.startingPage;
},
}, },
methods: { methods: {
prev () { prev () {
@@ -540,15 +616,11 @@ export default {
for (let key in set) { for (let key in set) {
let value = set[key]; let value = set[key];
if (type === 'background') key = value.key; if (type === 'background') key = value.key;
if (this.user.purchased[type][key]) setOwnedByUser = true; if (this.user.purchased[type][key]) setOwnedByUser = true;
} }
// let setOwnedByUser = find(set, (value, key) => {
// console.log(type)
// if (type === 'background') key = value.key;
// return this.user.purchased[type][key];
// });
return Boolean(setOwnedByUser); return setOwnedByUser;
}, },
/** /**
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase * For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
@@ -557,7 +629,7 @@ export default {
*/ */
async unlock (path) { async unlock (path) {
let fullSet = path.indexOf(',') !== -1; let fullSet = path.indexOf(',') !== -1;
let isBackground = Boolean(path.indexOf('background.')); let isBackground = path.indexOf('background.') !== -1;
let cost; let cost;
@@ -579,13 +651,17 @@ export default {
// if (this.user.balance < cost) return $rootScope.openModal('buyGems'); // if (this.user.balance < cost) return $rootScope.openModal('buyGems');
} }
} }
// @TODO: Add when we implment the user calls
// let response = await axios.post('/api/v3/user/unlock'); await axios.post(`/api/v3/user/unlock?path=${path}`);
try {
unlock(this.user, { unlock(this.user, {
query: { query: {
path, path,
}, },
}); });
} catch (e) {
alert(e.message);
}
}, },
setKeys (type, _set) { setKeys (type, _set) {
return map(_set, (v, k) => { return map(_set, (v, k) => {

View File

@@ -9,7 +9,6 @@ import getStore from './store';
import StoreModule from './libs/store'; import StoreModule from './libs/store';
import './filters/registerGlobals'; import './filters/registerGlobals';
import i18n from './libs/i18n'; import i18n from './libs/i18n';
import axios from 'axios';
import Notifications from 'vue-notification'; import Notifications from 'vue-notification';
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
@@ -24,16 +23,6 @@ Vue.config.performance = !IS_PRODUCTION;
// Disable annoying reminder abour production build in dev mode // Disable annoying reminder abour production build in dev mode
Vue.config.productionTip = IS_PRODUCTION; Vue.config.productionTip = IS_PRODUCTION;
axios.interceptors.response.use((response) => {
return response;
}, (error) => {
if (error.response.status >= 400) {
alert(error.response.data.message);
}
return Promise.reject(error);
});
Vue.use(Notifications); Vue.use(Notifications);
Vue.use(i18n); Vue.use(i18n);
Vue.use(StoreModule); Vue.use(StoreModule);

View File

@@ -92,7 +92,7 @@ Vue.use(VueRouter);
const router = new VueRouter({ const router = new VueRouter({
mode: 'history', mode: 'history',
base: process.env.NODE_ENV === 'production' ? '/new-app' : __dirname, // eslint-disable-line no-process-env base: process.env.NODE_ENV === 'production' ? '/' : __dirname, // eslint-disable-line no-process-env
linkActiveClass: 'active', linkActiveClass: 'active',
// When navigating to another route always scroll to the top // When navigating to another route always scroll to the top
// To customize the behavior see https://router.vuejs.org/en/advanced/scroll-behavior.html // To customize the behavior see https://router.vuejs.org/en/advanced/scroll-behavior.html

View File

@@ -60,6 +60,8 @@ export default function () {
}, },
avatarEditorOptions: { avatarEditorOptions: {
editingUser: false, editingUser: false,
startingPage: '',
subPage: '',
}, },
flagChatOptions: { flagChatOptions: {
message: {}, message: {},

View File

@@ -1,18 +1,18 @@
import locals from '../../middlewares/locals'; import locals from '../../middlewares/locals';
import _ from 'lodash'; // import _ from 'lodash';
import md from 'habitica-markdown'; // import md from 'habitica-markdown';
import nconf from 'nconf'; // import nconf from 'nconf';
let api = {}; let api = {};
const IS_PROD = nconf.get('IS_PROD'); // const IS_PROD = nconf.get('IS_PROD');
const TOTAL_USER_COUNT = '2,000,000'; // const TOTAL_USER_COUNT = '2,000,000';
const LOADING_SCREEN_TIPS = 33; const LOADING_SCREEN_TIPS = 33;
const IS_NEW_CLIENT_ENABLED = nconf.get('NEW_CLIENT_ENABLED') === 'true'; // const IS_NEW_CLIENT_ENABLED = nconf.get('NEW_CLIENT_ENABLED') === 'true';
api.getFrontPage = { api.getFrontPage = {
method: 'GET', method: 'GET',
url: '/', url: '/old-client',
middlewares: [locals], middlewares: [locals],
runCron: false, runCron: false,
async handler (req, res) { async handler (req, res) {
@@ -28,76 +28,75 @@ api.getFrontPage = {
}, },
}; };
let staticPages = ['front', 'privacy', 'terms', 'features', 'login', // let staticPages = ['front', 'privacy', 'terms', 'features', 'login',
'videos', 'contact', 'plans', 'new-stuff', 'community-guidelines', // 'videos', 'contact', 'plans', 'new-stuff', 'community-guidelines',
'old-news', 'press-kit', 'faq', 'overview', 'apps', // 'old-news', 'press-kit', 'faq', 'overview', 'apps',
'clear-browser-data', 'merch', 'maintenance-info']; // 'clear-browser-data', 'merch', 'maintenance-info'];
_.each(staticPages, (name) => { // _.each(staticPages, (name) => {
api[`get${name}Page`] = { // api[`get${name}Page`] = {
method: 'GET', // method: 'GET',
url: `/static/${name}`, // url: `/static/${name}`,
middlewares: [locals], // middlewares: [locals],
runCron: false, // runCron: false,
async handler (req, res) { // async handler (req, res) {
return res.render(`static/${name}.jade`, { // return res.render(`static/${name}.jade`, {
env: res.locals.habitrpg, // env: res.locals.habitrpg,
md, // md,
userCount: TOTAL_USER_COUNT, // userCount: TOTAL_USER_COUNT,
}); // });
}, // },
}; // };
}); // });
api.redirectApi = { // api.redirectApi = {
method: 'GET', // method: 'GET',
url: '/static/api', // url: '/static/api',
runCron: false, // runCron: false,
async handler (req, res) { // async handler (req, res) {
res.redirect(301, '/apidoc'); // res.redirect(301, '/apidoc');
}, // },
}; // };
let shareables = ['level-up', 'hatch-pet', 'raise-pet', 'unlock-quest', 'won-challenge', 'achievement']; // let shareables = ['level-up', 'hatch-pet', 'raise-pet', 'unlock-quest', 'won-challenge', 'achievement'];
_.each(shareables, (name) => { // _.each(shareables, (name) => {
api[`get${name}ShareablePage`] = { // api[`get${name}ShareablePage`] = {
method: 'GET', // method: 'GET',
url: `/social/${name}`, // url: `/social/${name}`,
middlewares: [locals], // middlewares: [locals],
runCron: false, // runCron: false,
async handler (req, res) { // async handler (req, res) {
return res.render(`social/${name}`, { // return res.render(`social/${name}`, {
env: res.locals.habitrpg, // env: res.locals.habitrpg,
md, // md,
userCount: TOTAL_USER_COUNT, // userCount: TOTAL_USER_COUNT,
}); // });
}, // },
}; // };
}); // });
api.redirectExtensionsPage = { // api.redirectExtensionsPage = {
method: 'GET', // method: 'GET',
url: '/static/extensions', // url: '/static/extensions',
runCron: false, // runCron: false,
async handler (req, res) { // async handler (req, res) {
return res.redirect('http://habitica.wikia.com/wiki/Extensions,_Add-Ons,_and_Customizations'); // return res.redirect('http://habitica.wikia.com/wiki/Extensions,_Add-Ons,_and_Customizations');
}, // },
}; // };
// All requests to /new_app (except /new_app/static) should serve the new client in development // All requests to /new_app (except /new_app/static) should serve the new client in development
if (IS_PROD && IS_NEW_CLIENT_ENABLED) { // if (IS_PROD && IS_NEW_CLIENT_ENABLED) {
api.getNewClient = { api.getNewClient = {
method: 'GET', method: 'GET',
url: /^\/new-app($|\/(?!(static\/.?|static$)))/, url: '/',
async handler (req, res) { async handler (req, res) {
if (!(req.session && req.session.userId)) { if (!(req.session && req.session.userId)) {
return res.redirect('/static/front'); return res.redirect('/');
} }
return res.sendFile('./dist-client/index.html', {root: `${__dirname}/../../../../`}); return res.sendFile('./dist-client/index.html', {root: `${__dirname}/../../../../`});
}, },
}; };
} // }
module.exports = api; module.exports = api;

View File

@@ -10,10 +10,10 @@ import staticMiddleware from './static';
import domainMiddleware from './domain'; import domainMiddleware from './domain';
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import compression from 'compression'; import compression from 'compression';
import favicon from 'serve-favicon'; // import favicon from 'serve-favicon';
import methodOverride from 'method-override'; import methodOverride from 'method-override';
import passport from 'passport'; import passport from 'passport';
import path from 'path'; // import path from 'path';
import maintenanceMode from './maintenanceMode'; import maintenanceMode from './maintenanceMode';
import { import {
forceSSL, forceSSL,
@@ -31,7 +31,7 @@ import basicAuth from 'express-basic-auth';
const IS_PROD = nconf.get('IS_PROD'); const IS_PROD = nconf.get('IS_PROD');
const DISABLE_LOGGING = nconf.get('DISABLE_REQUEST_LOGGING') === 'true'; const DISABLE_LOGGING = nconf.get('DISABLE_REQUEST_LOGGING') === 'true';
const ENABLE_HTTP_AUTH = nconf.get('SITE_HTTP_AUTH:ENABLED') === 'true'; const ENABLE_HTTP_AUTH = nconf.get('SITE_HTTP_AUTH:ENABLED') === 'true';
const PUBLIC_DIR = path.join(__dirname, '/../../client-old'); // const PUBLIC_DIR = path.join(__dirname, '/../../client');
const SESSION_SECRET = nconf.get('SESSION_SECRET'); const SESSION_SECRET = nconf.get('SESSION_SECRET');
const TWO_WEEKS = 1000 * 60 * 60 * 24 * 14; const TWO_WEEKS = 1000 * 60 * 60 * 24 * 14;
@@ -49,7 +49,7 @@ module.exports = function attachMiddlewares (app, server) {
app.use(attachTranslateFunction); app.use(attachTranslateFunction);
app.use(compression()); app.use(compression());
app.use(favicon(`${PUBLIC_DIR}/favicon.ico`)); // app.use(favicon(`${PUBLIC_DIR}/favicon.ico`));
app.use(maintenanceMode); app.use(maintenanceMode);

View File

@@ -3,17 +3,17 @@ import nconf from 'nconf';
import path from 'path'; import path from 'path';
const IS_PROD = nconf.get('IS_PROD'); const IS_PROD = nconf.get('IS_PROD');
const IS_NEW_CLIENT_ENABLED = nconf.get('NEW_CLIENT_ENABLED') === 'true'; // const IS_NEW_CLIENT_ENABLED = nconf.get('NEW_CLIENT_ENABLED') === 'true';
const MAX_AGE = IS_PROD ? 31536000000 : 0; const MAX_AGE = IS_PROD ? 31536000000 : 0;
const ASSETS_DIR = path.join(__dirname, '/../../assets'); const ASSETS_DIR = path.join(__dirname, '/../../assets');
const PUBLIC_DIR = path.join(__dirname, '/../../client-old'); const PUBLIC_DIR = path.join(__dirname, '/../../client');
const BUILD_DIR = path.join(__dirname, '/../../build'); const BUILD_DIR = path.join(__dirname, '/../../build');
module.exports = function staticMiddleware (expressApp) { module.exports = function staticMiddleware (expressApp) {
// Expose static files for new client // Expose static files for new client
if (IS_PROD && IS_NEW_CLIENT_ENABLED) { // if (IS_PROD && IS_NEW_CLIENT_ENABLED) {
expressApp.use('/new-app/static', express.static(`${PUBLIC_DIR}/../../dist-client/static`)); expressApp.use('/static', express.static(`${PUBLIC_DIR}/../../dist-client/static`));
} // }
// TODO move all static files to a single location (one for public and one for build) // TODO move all static files to a single location (one for public and one for build)
expressApp.use(express.static(BUILD_DIR, { maxAge: MAX_AGE })); expressApp.use(express.static(BUILD_DIR, { maxAge: MAX_AGE }));