New client footer (#8954)

* Minor footer style fixes

* Added initial gem modal

* Fixed some heroe stuff.

* Preventing system member loading

* Added social delete
This commit is contained in:
Keith Holliday
2017-08-16 10:05:33 -06:00
committed by GitHub
parent 8614f11a31
commit 0bff37b600
10 changed files with 247 additions and 52 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="16" viewBox="0 0 18 16">
<path fill="#F19595" fill-rule="evenodd" d="M17.676 3.065c-.449-1.107-1.35-2.039-2.595-2.615a4.8 4.8 0 0 0-3.366-.26C10.637.502 9.668 1.35 9 2.332 8.332 1.351 7.363.502 6.285.19a4.8 4.8 0 0 0-3.366.26C1.673 1.026.773 1.958.324 3.065c-.449 1.107-.45 2.393.115 3.671C1.649 9.471 8.962 15.89 8.999 16c.04-.11 7.352-6.529 8.562-9.264.566-1.278.564-2.564.115-3.671"/>
</svg>

After

Width:  |  Height:  |  Size: 458 B

View File

@@ -1,5 +1,6 @@
<template lang="pug"> <template lang="pug">
.row .row
buy-gems-modal
modify-inventory modify-inventory
footer.container-fluid footer.container-fluid
.row .row
@@ -59,14 +60,14 @@
a(href='http://habitica.wikia.com/wiki/Guidance_for_Blacksmiths', target='_blank') Guidance for Blacksmiths a(href='http://habitica.wikia.com/wiki/Guidance_for_Blacksmiths', target='_blank') Guidance for Blacksmiths
li li
a(href='http://devs.habitica.com/', target='_blank') The Forge - Developer Blog a(href='http://devs.habitica.com/', target='_blank') The Forge - Developer Blog
.col-6 .col-6.social
h3 Social h3 Social
.social-circle .social-circle
a(href='https://twitter.com/habitica', target='_blank') a(href='https://twitter.com/habitica', target='_blank')
.social-icon.svg-icon(v-html='icons.twitter') .social-icon.svg-icon(v-html='icons.twitter')
.social-circle .social-circle
a(href='https://www.instagram.com/habitica/', target='_blank') a(href='https://www.instagram.com/habitica/', target='_blank')
.social-icon.svg-icon(v-html='icons.instagram') .social-icon.svg-icon.instagram(v-html='icons.instagram')
.social-circle .social-circle
a(href='https://www.facebook.com/Habitica', target='_blank') a(href='https://www.facebook.com/Habitica', target='_blank')
.social-icon.facebook.svg-icon(v-html='icons.facebook') .social-icon.facebook.svg-icon(v-html='icons.facebook')
@@ -74,7 +75,9 @@
.col-10 .col-10
| Were an open source project that depends on our users for support. The money you donate helps us keep the servers running, maintain a small staff, develop new features, and provide incentives for our volunteers. | Were an open source project that depends on our users for support. The money you donate helps us keep the servers running, maintain a small staff, develop new features, and provide incentives for our volunteers.
.col-2 .col-2
button.btn.btn-primary Donate button.btn.btn-donate(@click='donate()')
.svg-icon.heart(v-html='icons.heart')
.text Donate
.row .row
hr.col-12 hr.col-12
.row .row
@@ -99,10 +102,12 @@
a.btn.btn-default(@click='makeAdmin()') Make Admin a.btn.btn-default(@click='makeAdmin()') Make Admin
a.btn.btn-default(@click='openModifyInventoryModal()') Modify Inventory a.btn.btn-default(@click='openModifyInventoryModal()') Modify Inventory
.col-4.text-center .col-4.text-center
.logo.svg-icon(v-html='icons.gryphon') .logo
.col-4.text-right .col-4.text-right
span Privacy Policy span
span Terms of Use router-link(to="/static/privacy") Privacy Policy
span.terms-link
router-link(to="/static/terms") Terms of Use
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -114,6 +119,10 @@
padding-top: 3em; padding-top: 3em;
margin: 0; margin: 0;
color: #878190; color: #878190;
a {
color: #878190;
}
} }
h3 { h3 {
@@ -129,13 +138,20 @@
margin-bottom: .5em; margin-bottom: .5em;
} }
.social {
h3 {
text-align: right;
}
}
.social-circle { .social-circle {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 50%; border-radius: 50%;
background-color: #c3c0c7; background-color: #c3c0c7;
display: inline-block; display: inline-block;
margin-right: 1em; margin-left: 1em;
float: right;
.social-icon { .social-icon {
color: #e1e0e3; color: #e1e0e3;
@@ -144,15 +160,26 @@
margin-top: 1em; margin-top: 1em;
} }
.svg-icon.facebook svg { .facebook {
height: 20px; margin-top: .7em;
}
.instagram {
margin-top: .85em;
} }
} }
.logo.svg-icon { .logo {
background-image: url('~assets/images/gryphon@3x.png');
width: 24px; width: 24px;
height: 24px;
margin: 0 auto; margin: 0 auto;
color: #c3c0c7; color: #c3c0c7;
background-size: cover;
}
.terms-link {
margin-left: 1em;
} }
.debug-group { .debug-group {
@@ -162,6 +189,30 @@
border-radius: 2px; border-radius: 2px;
padding: 2em; padding: 2em;
} }
.btn-donate {
background: #c3c0c7;
box-shadow: none;
border-radius: 4px;
.heart {
width: 18px;
margin-right: .5em;
margin-bottom: .2em;
}
.text, .heart {
display: inline-block;
vertical-align: bottom;
}
}
</style>
<style>
.facebook svg {
width: 10px;
margin: 0 auto;
}
</style> </style>
<script> <script>
@@ -173,14 +224,17 @@ import gryphon from 'assets/svg/gryphon.svg';
import twitter from 'assets/svg/twitter.svg'; import twitter from 'assets/svg/twitter.svg';
import facebook from 'assets/svg/facebook.svg'; import facebook from 'assets/svg/facebook.svg';
import instagram from 'assets/svg/instagram.svg'; import instagram from 'assets/svg/instagram.svg';
import heart from 'assets/svg/heart.svg';
import modifyInventory from './modifyInventory'; import modifyInventory from './modifyInventory';
import buyGemsModal from './payments/buyGemsModal';
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
export default { export default {
components: { components: {
modifyInventory, modifyInventory,
buyGemsModal,
}, },
data () { data () {
return { return {
@@ -189,6 +243,7 @@ export default {
twitter, twitter,
facebook, facebook,
instagram, instagram,
heart,
}), }),
debugMenuShown: false, debugMenuShown: false,
IS_PRODUCTION, IS_PRODUCTION,
@@ -275,6 +330,9 @@ export default {
openModifyInventoryModal () { openModifyInventoryModal () {
this.$root.$emit('show::modal', 'modify-inventory'); this.$root.$emit('show::modal', 'modify-inventory');
}, },
donate () {
this.$root.$emit('show::modal', 'buy-gems');
},
}, },
}; };
</script> </script>

View File

@@ -166,7 +166,8 @@ export default {
this.messages.forEach(message => { this.messages.forEach(message => {
let uuid = message.uuid; let uuid = message.uuid;
if (!this.cachedProfileData[uuid]) { if (uuid && !this.cachedProfileData[uuid]) {
if (uuid === 'system') return;
promises.push(axios.get(`/api/v3/members/${uuid}`)); promises.push(axios.get(`/api/v3/members/${uuid}`));
} }
}); });

View File

@@ -3,13 +3,13 @@
small.muted(v-html="$t('blurbHallContributors')") small.muted(v-html="$t('blurbHallContributors')")
.well(v-if='user.contributor.admin') .well(v-if='user.contributor.admin')
h2 {{ $t('rewardUser') }} h2 {{ $t('rewardUser') }}
form(v-submit='loadHero(_heroID)') form(submit='loadHero(heroID)') // @TODO: make click
.form-group .form-group
input.form-control(type='text', v-model='_heroID', placeholder {{ $t('UUID') }}) input.form-control(type='text', v-model='heroID', placeholder="$t('UUID')")
.form-group .form-group
input.btn.btn-default(type='submit') input.btn.btn-default(type='submit')
| {{ $t('loadUser') }} | {{ $t('loadUser') }}
form(v-show='hero', v-submit='saveHero(hero)') form(v-if='hero && hero.profile', submit='saveHero(hero)') // @TODO: make click
a(v-click='clickMember(hero._id, true)') a(v-click='clickMember(hero._id, true)')
h3 {{hero.profile.name}} h3 {{hero.profile.name}}
.form-group .form-group
@@ -70,19 +70,19 @@
thead thead
tr tr
th {{ $t('name') }} th {{ $t('name') }}
th(v-if='user.contributor.admin') {{ $t('UUID') }} th(v-if='user.contributor && user.contributor.admin') {{ $t('UUID') }}
th {{ $t('contribLevel') }} th {{ $t('contribLevel') }}
th {{ $t('title') }} th {{ $t('title') }}
th {{ $t('contributions') }} th {{ $t('contributions') }}
tbody tbody
tr(v-repeat='hero in heroes') tr(v-for='(hero, $index) in heroes')
td td
span(v-if='hero.contributor.admin', :popover="$t('gamemaster')", popover-trigger='mouseenter', popover-placement='right') span(v-if='hero.contributor && hero.contributor.admin', :popover="$t('gamemaster')", popover-trigger='mouseenter', popover-placement='right')
a.label.label-default(v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)') a.label.label-default(v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)')
| {{hero.profile.name}}&nbsp; | {{hero.profile.name}}&nbsp;
span(v-class='userAdminGlyphiconStyle(hero)') span(v-class='userAdminGlyphiconStyle(hero)')
span(v-if='!hero.contributor.admin') span(v-if='!hero.contributor || !hero.contributor.admin')
a.label.label-default(v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)') {{hero.profile.name}} a.label.label-default(v-if='hero.profile', v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)') {{hero.profile.name}}
td(v-if='user.contributor.admin', v-click='populateContributorInput(hero._id, $index)').btn-link {{hero._id}} td(v-if='user.contributor.admin', v-click='populateContributorInput(hero._id, $index)').btn-link {{hero._id}}
td {{hero.contributor.level}} td {{hero.contributor.level}}
td {{hero.contributor.text}} td {{hero.contributor.text}}
@@ -91,7 +91,7 @@
</template> </template>
<script> <script>
import keys from 'lodash/keys'; // import keys from 'lodash/keys';
import each from 'lodash/each'; import each from 'lodash/each';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
@@ -105,6 +105,7 @@ export default {
return { return {
heroes: [], heroes: [],
hero: {}, hero: {},
heroID: '',
currentHeroIndex: -1, currentHeroIndex: -1,
allItemPaths: this.getAllItemPaths(), allItemPaths: this.getAllItemPaths(),
quests, quests,
@@ -124,22 +125,22 @@ export default {
}, },
methods: { methods: {
getAllItemPaths () { getAllItemPaths () {
let questsFormat = this.getFormattedItemReference('items.quests', keys(this.quests), 'Numeric Quantity'); // let questsFormat = this.getFormattedItemReference('items.quests', keys(this.quests), 'Numeric Quantity');
let mountsFormat = this.getFormattedItemReference('items.mounts', keys(this.mountInfo), 'Boolean'); // let mountsFormat = this.getFormattedItemReference('items.mounts', keys(this.mountInfo), 'Boolean');
let foodFormat = this.getFormattedItemReference('items.food', keys(this.food), 'Numeric Quantity'); // let foodFormat = this.getFormattedItemReference('items.food', keys(this.food), 'Numeric Quantity');
let eggsFormat = this.getFormattedItemReference('items.eggs', keys(this.eggs), 'Numeric Quantity'); // let eggsFormat = this.getFormattedItemReference('items.eggs', keys(this.eggs), 'Numeric Quantity');
let hatchingPotionsFormat = this.getFormattedItemReference('items.hatchingPotions', keys(this.hatchingPotions), 'Numeric Quantity'); // let hatchingPotionsFormat = this.getFormattedItemReference('items.hatchingPotions', keys(this.hatchingPotions), 'Numeric Quantity');
let petsFormat = this.getFormattedItemReference('items.pets', keys(this.petInfo), '-1: Owns Mount, 0: Not Owned, 1-49: Progress to mount'); // let petsFormat = this.getFormattedItemReference('items.pets', keys(this.petInfo), '-1: Owns Mount, 0: Not Owned, 1-49: Progress to mount');
let specialFormat = this.getFormattedItemReference('items.special', keys(this.special), 'Numeric Quantity'); // let specialFormat = this.getFormattedItemReference('items.special', keys(this.special), 'Numeric Quantity');
let gearFormat = this.getFormattedItemReference('items.gear.owned', keys(this.gear.flat), 'Boolean'); // let gearFormat = this.getFormattedItemReference('items.gear.owned', keys(this.gear.flat), 'Boolean');
//
let equippedGearFormat = '\nEquipped Gear:\n\titems.gear.{equipped/costume}.{head/headAccessory/eyewear/armor/body/back/shield/weapon}.{gearKey}\n'; // let equippedGearFormat = ''; // @TODO: '\nEquipped Gear:\n\titems.gear.{equipped/costume}.{head/headAccessory/eyewear/armor/body/back/shield/weapon}.{gearKey}\n';
let equippedPetFormat = '\nEquipped Pet:\n\titems.currentPet.{petKey}\n'; // let equippedPetFormat = ''; // @TODO: '\nEquipped Pet:\n\titems.currentPet.{petKey}\n';
let equippedMountFormat = '\nEquipped Mount:\n\titems.currentMount.{mountKey}\n'; // let equippedMountFormat = ''; // @TODO: '\nEquipped Mount:\n\titems.currentMount.{mountKey}\n';
//
let data = questsFormat.concat(mountsFormat, foodFormat, eggsFormat, hatchingPotionsFormat, petsFormat, specialFormat, gearFormat, equippedGearFormat, equippedPetFormat, equippedMountFormat); // let data = questsFormat.concat(mountsFormat, foodFormat, eggsFormat, hatchingPotionsFormat, petsFormat, specialFormat, gearFormat, equippedGearFormat, equippedPetFormat, equippedMountFormat);
//
return data; // return data;
}, },
getFormattedItemReference (pathPrefix, itemKeys, values) { getFormattedItemReference (pathPrefix, itemKeys, values) {
let finishedString = '\n'.concat('path: ', pathPrefix, ', ', 'value: {', values, '}\n'); let finishedString = '\n'.concat('path: ', pathPrefix, ', ', 'value: {', values, '}\n');
@@ -152,6 +153,7 @@ export default {
}, },
async loadHero (uuid, heroIndex) { async loadHero (uuid, heroIndex) {
this.currentHeroIndex = heroIndex; this.currentHeroIndex = heroIndex;
if (!heroIndex) return;
let hero = await this.$store.dispatch('hall:getHero', { uuid }); let hero = await this.$store.dispatch('hall:getHero', { uuid });
this.hero = hero; this.hero = hero;
}, },
@@ -161,15 +163,21 @@ export default {
// @TODO: Import // @TODO: Import
// Notification.text("User updated"); // Notification.text("User updated");
this.hero = {}; this.hero = {};
this._heroID = -1; this.heroID = -1;
this.heroes[this.currentHeroIndex] = heroUpdated; this.heroes[this.currentHeroIndex] = heroUpdated;
this.currentHeroIndex = -1; this.currentHeroIndex = -1;
}, },
populateContributorInput (id, index) { populateContributorInput (id, index) {
this._heroID = id; this.heroID = id;
window.scrollTo(0, 200); window.scrollTo(0, 200);
this.loadHero(id, index); this.loadHero(id, index);
}, },
clickMember () {
// @TODO: implement
},
userLevelStyle () {
// @TODO: implement
},
}, },
}; };
</script> </script>

View File

@@ -0,0 +1,112 @@
<template lang="pug">
b-modal#buy-gems(title="Amazon", :hide-footer="true", size='lg')
.modal-body
.buy-gems
// @TODO: +gemButton(true)
div(ng-if='user.purchased.plan.customerId && (user.purchased.plan.gemsBought >= User.user.purchased.plan.consecutive.gemCapExtra + Shared.planGemLimits.convCap)')
.panel.panel-default
.panel-body
h3 {{ $t('buyGemsGold') }}
p {{ $t('maxBuyGems') }}
div(ng-if='user.purchased.plan.customerId && (user.purchased.plan.gemsBought < User.user.purchased.plan.consecutive.gemCapExtra + Shared.planGemLimits.convCap)')
.panel.panel-default
.panel-body
h3 {{ $t('buyGemsGold') }}
p {{ $t('subGemPop') }}
.container-fluid
.row
.col-md-3
button.customize-option(ng-click='User.purchase({params:{type:"gems",key:"gem"}})')
span.Pet_Currency_Gem.inline-gems
// @TODO: .badge.badge-success.stack-count {{Shared.planGemLimits.convCap + User.user.purchased.plan.consecutive.gemCapExtra - User.user.purchased.plan.gemsBought}}
p
| 20&nbsp;
span.shop_gold
.col-md-8
.popover.right.gem-count-popover
.arrow
.popover-content
p {{ $t('buyGemsAllow1') }}
// @TOOD: | &nbsp;{{Shared.planGemLimits.convCap + User.user.purchased.plan.consecutive.gemCapExtra - User.user.purchased.plan.gemsBought}}&nbsp;
| {{ $t('buyGemsAllow2') }}
p {{ $t('seeSubscriptionDetails') }}
div(ng-if='user.purchased.plan.customerId')
.well
h3 {{ $t('purchaseGemsSeparately') }}
.container-fluid
.row
.col-md-4.col-md-offset-4.alert.alert-info $5&nbsp;
| {{ $t('USD') }}
span#TotalGemPrice.dashed-underline(:popover="$t('donateText1')",
popover-trigger='mouseenter',popover-placement='bottom')
| +20
span(class="Pet_Currency_Gem1x inline-gems")
.container-fluid
.row
.col-md-10.col-md-offset-2
p
small.muted {{ $t('paymentMethods') }}
a.purchase.btn.btn-primary(ng-click='Payments.showStripe({})') {{ $t('card') }}
a.purchase(href='/paypal/checkout?_id=${user._id}&apiToken=${User.settings.auth.apiToken}')
img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png',alt='Pay now with Paypal')
a.purchase(ng-click="Payments.amazonPayments.init({type: 'single'})")
img(src='https://payments.amazon.com/gp/cba/button', alt='Pay now with Amazon Payments')
div(ng-if='!user.purchased.plan.customerId')
.panel.panel-default
.panel-body
h3 {{ $t('purchaseGems') }}
.small
span.dashed-underline(popover="$t('donateText3')", popover-trigger='mouseenter', popover-placement='bottom')
| {{ $t('donateText2') }}
.container-fluid
.row
.col-md-4.col-md-offset-4.alert.alert-info $5&nbsp;
| {{ $t('USD') }}
span#TotalGemPrice.dashed-underline(popover="$t('donateText1')",
popover-trigger='mouseenter', ement='bottom')
| +20
span(class="Pet_Currency_Gem1x inline-gems")
.container-fluid
.row
.col-md-10.col-md-offset-2
p
small.muted {{ $t('paymentMethods') }}
a.purchase.btn.btn-primary(ng-click='Payments.showStripe({})') {{ $t('card') }}
a.purchase(href='/paypal/checkout?_id=${user._id}&apiToken=${User.settings.auth.apiToken}')
img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png',
alt='Pay now with Paypal')
a.purchase(ng-click="Payments.amazonPayments.init({type: 'single'})")
img(src='https://payments.amazon.com/gp/cba/button', alt='Pay now with Amazon Payments')
.container-fluid
h3 {{ $t('freeGemsTitle') }}
p {{ $t('subFreeGemsHow') }}
.well
h3
.small {{ $t('buyGemsGoldTitle') }}
h3 {{ $t('becomeSubscriber') }}
div(ng-include="'partials/options.settings.subscription.html'", ng-controller='SettingsCtrl')
div(ng-if='user.purchased.plan.customerId').pull-left
p {{ $t('seeSubscriptionDetails') }}
.text-right
button.btn.btn-default(ng-click='$close()') {{ $t('close') }}
</template>
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
export default {
components: {
bModal,
},
methods: {
close () {
this.$root.$emit('hide::modal', 'buy-gems');
},
},
};
</script>

View File

@@ -1,18 +1,31 @@
<template lang="pug"> <template lang="pug">
b-modal#delete(:title="$t('deleteAccount')", :hide-footer='true' size='md') b-modal#delete(:title="$t('deleteAccount')", :hide-footer='true' size='md')
strong {{ $t('deleteLocalAccountText') }} .regular-delete(v-if='user.auth.local.email')
br strong {{ $t('deleteLocalAccountText') }}
.row br
.col-6 .row
input.form-control(type='password', v-model='password') .col-6
br input.form-control(type='password', v-model='password')
.row br
#feedback.col-12.form-group .row
label(for='feedbackTextArea') {{ $t('feedback') }} #feedback.col-12.form-group
textarea#feedbackTextArea.form-control(v-model='feedback') label(for='feedbackTextArea') {{ $t('feedback') }}
.modal-footer textarea#feedbackTextArea.form-control(v-model='feedback')
button.btn.btn-danger(@click='close()') {{ $t('neverMind') }} .modal-footer
button.btn.btn-primary(@click='deleteAccount()', :disabled='!password') {{ $t('deleteDo') }} button.btn.btn-danger(@click='close()') {{ $t('neverMind') }}
button.btn.btn-primary(@click='deleteAccount()', :disabled='!password') {{ $t('deleteDo') }}
.modal-header
.social-delete(v-if='!user.auth.local.email')
h4 {{ $t('deleteAccount') }}
.modal-body
p {{ $t('deleteSocialAccountText') }}
br
.row
.col-md-6
input.form-control(type='text', v-model='password')
.modal-footer
button.btn.btn-default(@click='close()') {{ $t('neverMind') }}
button.btn.btn-danger(:disabled='!password', @click='deleteAccount()') {{ $t('deleteDo') }}
</template> </template>
<script> <script>

View File

@@ -10,4 +10,4 @@ export function getMembers (store, forceLoad = false) {
}, },
forceLoad, forceLoad,
}); });
} }