Sept 15 fixes (#9044)

* Adjusted styles and added loading for private messages

* Allowed for assigning during group task creation

* Fixed white logos and start overflow

* Added state styles to home

* Fixed position

* Updated avatar purchasing
This commit is contained in:
Keith Holliday
2017-09-18 11:54:25 -05:00
committed by GitHub
parent ff92f14a5b
commit ccc862f82a
10 changed files with 413 additions and 83 deletions

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40">
<path fill-rule="evenodd" d="M35.907 26.51v-1.424s-.771-.01-1.182-.006c-.522.006-.973-.241-1.01-.975l.004-7.688-.005-.014h1.852V15.01h-1.858l.011-.022v-2.982h-1.938v11.946c.06 1.035.386 1.964 1.246 2.35l-.003-.001c-.02-.01-.02-.008 0 0l.012.005c-.003 0-.006-.002-.009-.004.097.04.56.22 1.034.215.316-.008 1.846-.006 1.846-.006zm-5.688-2.527V22.61h-1.926v1.466c0 1.423-2.477 1.444-2.503 0v-3.053l4.07.002a.353.353 0 0 0 .352-.353v-3.14c.12-3.802-6.393-3.797-6.342-.094v6.545c-.05 3.703 6.468 3.797 6.349 0zm-6.953 1.103h-1.22v-7.748c-.062-1.038-.39-1.969-1.257-2.351.156.067-.92-.54-2.02.07-.868.48-1.2.971-1.2.971l-.007-1.041h-2.715v1.416l1.06.007v8.676l-.894-.003v1.425h2.816V17.25c.088-1.311 2.297-1.332 2.297-.002l.002 9.26h3.138v-1.422zm-10.813 6.858h1.393V9.236h-1.393v22.708zm-1.285-7.96V22.61H9.241v1.466c0 1.423-2.476 1.444-2.501 0v-6.638l-.003.07c.024-1.447 2.504-1.489 2.504-.07l.023 1.23h1.896v-1.136c.123-3.803-6.394-3.797-6.343-.094v6.545c-.05 3.703 6.468 3.797 6.351 0zm28.83-3.982c0 11.046-8.954 19.998-20 19.998S0 31.047 0 20.002C0 8.954 8.952 0 19.998 0c11.046 0 20 8.954 20 20.002zm-11.71-.423l-2.498.001v-2.152c.033-1.42 2.503-1.409 2.503.01l-.005 2.14z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="162" height="24" viewBox="0 0 162 24">
<path fill-rule="evenodd" d="M17.08 7.351L15.46 12.65h3.352L17.08 7.35zm1.515 10.487v-.757c1.081 0 1.298-.324 1.298-.648 0-.433-.108-.757-.217-1.081 0 0-.216-.866-.432-1.514h-4.216l-.433 1.405c-.107.325-.215.65-.215 1.082 0 .433.432.756 1.08.756v.757h-4.215v-.757c1.08 0 1.513-.324 1.945-1.513l3.244-9.73c-.109-.433-.433-.757-1.081-.757v-.757h3.458c1.18 3.463 2.369 6.922 3.567 10.379.54 1.837 1.081 2.378 1.946 2.378v.757h-5.729zM66.162 6.162c-2.81 0-3.784 2.703-3.784 5.838 0 2.92.865 5.838 3.784 5.838 2.811 0 3.676-2.92 3.676-5.946 0-2.919-1.08-5.73-3.676-5.73zm0 12.973c-4.108 0-6.92-2.92-6.92-7.135 0-4 2.92-7.135 6.92-7.135 3.892 0 6.81 3.027 6.81 7.135.002 4-3.026 7.135-6.81 7.135zM102.81 2.27h-.54v11.134h.972c3.57 0 5.407-1.622 5.407-5.73 0-4.108-1.623-5.404-5.84-5.404zm1.08 12.757h-1.62v4.647c0 2.38.647 2.92 2.486 2.92v.864h-8.324v-.864c1.73 0 2.379-.648 2.379-3.027V4.325c0-2.378-.649-2.81-2.379-2.81V.757h6.27c6.054 0 9.62 1.838 9.62 6.81.001 5.19-4.322 7.46-8.431 7.46zM117.3 5.189l-3.028 9.839h6.27L117.3 5.189zm13.513 1.081v12.973c0 2.81.647 3.35 2.377 3.35v.866h-12.755v-.865c.974 0 1.837-.325 1.837-.973 0-.433-.107-1.19-.325-1.947l-.973-3.135h-7.134c-.11.434-1.405 4-1.405 4.974 0 .864.973 1.08 1.62 1.08v.866h-5.946v-.865c1.081 0 1.947-.108 2.703-2.378l5.514-17.622c-.325-.757-.756-.973-1.513-1.082V.756h4.866l5.836 18.487c.541 1.946 1.08 2.92 1.946 3.35 1.298-.431 1.623-.864 1.623-3.35V3.676c-.974-1.298-1.083-2.163-2.92-2.163V.757h5.514l9.081 15.46V4.432c0-2.379-.54-2.92-2.379-2.92V.757h12.108v.756c-.756 0-1.405.325-1.405 1.082 0 .54.217 1.08.433 1.73l3.46 7.46 3.351-7.244c.54-.973.65-1.513.65-2.054 0-.649-.435-.974-1.406-.974V.757h5.729v.756c-1.405 0-2.272 1.298-2.919 2.81l-4.432 9.082v5.946c0 2.596.648 3.244 2.378 3.244v.864h-8.217v-.864c1.73 0 2.38-.648 2.38-3.244v-5.08L145.73 4.216c-.864-1.945-1.189-2.378-1.73-2.703-1.082.433-1.406 1.19-1.406 2.92V21.08s.11 1.298.217 2.81l-1.405.109-10.595-17.73zM14.162 4.973h-.864c0-1.946-.865-2.702-2.595-2.702H5.838v8.54h3.135c1.622 0 1.947-.864 2.162-2.27h.757v6.054h-.757c-.215-1.621-.54-2.27-2.27-2.27H5.838v7.244c0 2.702.649 3.027 2.379 3.027v.864H0v-.864c2.054 0 2.378-.54 2.378-3.027V3.676c0-1.514-.649-2.163-2.378-2.163V.757h11.243C13.188.757 13.62.65 13.946 0h.757l-.54 4.973zM26.486 24c-1.513 0-2.703-.216-3.567-.54-.865-.216-1.514-.541-1.838-.757a5.804 5.804 0 0 0-.757.973l-.649-.216.54-5.08.758.108c.432 2.378 2.054 4.108 5.406 4.108 2.594 0 4.324-2.162 4.324-4.54 0-1.946-.757-2.92-3.351-4.866-.865-.54-1.622-.972-2.271-1.513-2.378-1.513-3.892-3.243-3.892-6.054 0-3.243 2.703-5.405 6.27-5.405 2.054 0 3.352.648 3.784.864l.756-.864.54.108L32 4.974l-.756-.108c0-2.161-1.298-3.135-3.46-3.135-2.054 0-3.567 1.081-3.567 3.135 0 1.838 1.405 3.027 3.026 4.109.865.54 1.514.973 2.162 1.405 3.784 2.702 4.648 4.432 4.648 7.027C34.054 21.19 31.135 24 26.486 24zM49.405 4.973h-.756c-.109-2.054-.757-2.702-2.38-2.702h-3.134v16.973c0 2.81.54 3.35 2.379 3.35v.865h-8.109v-.864c1.838 0 2.379-.54 2.379-3.46V2.27h-3.135c-2.054 0-2.38.54-2.92 2.702h-.756l.54-4.865.541.109c.216.54.65.54 1.946.54h10.486c1.947 0 2.38 0 2.812-.649h.648l-.541 4.865zm20.433 18.595c-.432-.109-.864-.109-1.297-.109-.865 0-2.38.433-4.217.433-7.027 0-12.216-4.217-12.216-12 0-6.595 4.865-11.675 12.324-11.675 1.729 0 3.676.324 5.297.972.324-.324.433-.54.757-.864h.648c-.108 1.19-.54 5.08-.54 5.08h-.65c-.431-2.269-1.62-3.783-5.405-3.783-4.54 0-8.648 3.567-8.648 10.162 0 7.46 4.216 10.703 8.865 10.703 3.028 0 4.865-1.73 6.054-3.892l.758.325-1.73 4.648zM76.65 6.487c0 3.243-.324 13.298-.324 13.298 0 1.945.648 2.81 2.487 2.81v.864h-7.244v-.864c1.838 0 2.81-.865 2.81-2.81l.65-16.433c-.541-1.298-1.082-1.73-2.487-1.838V.758h5.513l5.838 15.352L89.84.758h4.972v.756c-1.405 0-2.161.65-2.161 2.163l.649 15.892c0 2.379.432 3.027 2.379 3.027v.864h-8.325v-.864c1.621 0 2.38-.54 2.27-3.027 0 0-.325-11.136-.432-13.081l-3.999 11.027a41.15 41.15 0 0 0-1.514 4.757l-1.296.108c-.325-1.19-1.19-3.35-1.19-3.35S77.838 9.621 76.65 6.486z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -184,6 +184,9 @@
#bottom-wrap {
margin-top: 6em;
position: fixed;
width: 100%;
bottom: 0;
}
#bottom-background {

View File

@@ -14,7 +14,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
// @TODO Implement in V2 .section.row
.col-12.text-center
button.btn.btn-secondary(v-once) {{$t('randomize')}}
.container.section.text-center.customize-menu
#options-nav.container.section.text-center.customize-menu
.row
div(:class='{"col-3": !editing, "col-2 offset-1": editing}')
.menu-item(@click='changeTopPage("body", "size")')
@@ -36,8 +36,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
.menu-item(@click='changeTopPage("backgrounds", "2017")')
.svg-icon(v-html='icons.backgroundsIcon')
strong(v-once) {{$t('backgrounds')}}
.section.customize-section(v-if='activeTopPage === "body"')
#body.section.customize-section(v-if='activeTopPage === "body"')
.row.sub-menu.col-6.offset-3.text-center
.col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}')
strong(v-once) {{$t('size')}}
@@ -53,16 +52,15 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
:class='{active: user.preferences.shirt === option}')
.sprite.customize-option(:class="`slim_shirt_${option}`", @click='set({"preferences.shirt": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in specialShirts',
:class='{active: user.preferences.shirt === option, locked: !user.purchased.shirt[option]}')
.sprite.customize-option(:class="`broad_shirt_${option}`", @click='user.purchased.shirt[option] ? set({"preferences.shirt": option}) : unlock(`shirt.${option}`)')
.gem-lock(v-if='!user.purchased.shirt[option]')
.option(v-for='item in specialShirts',
:class='{active: item.active, locked: item.locked}')
.sprite.customize-option(:class="`broad_shirt_${item.key}`", @click='item.click')
.gem-lock(v-if='item.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary(@click='unlock(`shirt.${specialShirts.join(",shirt.")}`)') Purchase All
.section.customize-section(v-if='activeTopPage === "skin"')
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("shirt", specialShirtKeys)', @click='unlock(`shirt.${specialShirtKeys.join(",shirt.")}`)') $t('purchaseAll')
#skin.section.customize-section(v-if='activeTopPage === "skin"')
.row.sub-menu.col-6.offset-3.text-center
.col-6.offset-3.text-center.sub-menu-item(:class='{active: activeSubPage === "color"}')
strong(v-once) {{$t('color')}}
@@ -73,41 +71,69 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
.skin.sprite.customize-option(:class="`skin_${option}`", @click='set({"preferences.skin": option})')
.row(v-if='editing')
.col-12.customize-options
.option(v-for='option in ["eb052b", "f69922", "f5d70f", "0ff591", "2b43f6", "d7a9f7", "800ed0", "rainbow"]',
:class='{active: user.preferences.skin === option, locked: !user.purchased.skin[option]}')
.skin.sprite.customize-option(:class="`skin_${option}`", @click='user.purchased.skin[option] ? set({"preferences.skin": option}) : unlock(`skin.${option}`)')
.gem-lock(v-if='!user.purchased.skin[option]')
.option(v-for='option in rainbowSkins',
:class='{active: option.active, locked: option.locked}')
.skin.sprite.customize-option(:class="`skin_${option.key}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("skin", rainbowSkinKeys)', @click='unlock(`skin.${rainbowSkinKeys.join(",skin.")}`)') $t('purchaseAll')
.row(v-if='editing')
.col-12.customize-options
.option(v-for='option in ["bear", "cactus", "fox", "lion", "panda", "pig", "tiger", "wolf"]',
:class='{active: user.preferences.skin === option, locked: !user.purchased.skin[option]}')
.skin.sprite.customize-option(:class="`skin_${option}`", @click='user.purchased.skin[option] ? set({"preferences.skin": option}) : unlock(`skin.${option}`)')
.gem-lock(v-if='!user.purchased.skin[option]')
.option(v-for='option in animalSkins',
:class='{active: option.active, locked: option.locked}')
.skin.sprite.customize-option(:class="`skin_${option.key}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("skin", animalSkinKeys)', @click='unlock(`skin.${animalSkinKeys.join(",skin.")}`)') $t('purchaseAll')
#hair.section.customize-section(v-if='activeTopPage === "hair"')
.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-1.text-center.sub-menu-item(@click='changeSubPage("color")', :class='{active: activeSubPage === "color"}')
strong(v-once) {{$t('color')}}
.col-2.text-center.sub-menu-item(@click='changeSubPage("style")', :class='{active: activeSubPage === "style"}', v-if='editing')
strong(v-once) {{$t('style')}}
.col-2.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}')
strong(v-once) {{$t('bangs')}}
.col-3.text-center.sub-menu-item(@click='changeSubPage("ponytail")', :class='{active: activeSubPage === "ponytail"}')
strong(v-once) {{$t('ponytail')}}
.row(v-if='activeSubPage === "color"')
.col-2.text-center.sub-menu-item(@click='changeSubPage("facialhair")', :class='{active: activeSubPage === "facialhair"}', v-if='editing')
strong(v-once) {{$t('facialhair')}}
#hair-color.row(v-if='activeSubPage === "color"')
.col-12.customize-options
.option(v-for='option in ["white", "brown", "blond", "red", "black"]',
:class='{active: user.preferences.hair.color === option}')
.color-bangs.sprite.customize-option(:class="`hair_bangs_1_${option}`", @click='set({"preferences.hair.color": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["rainbow", "yellow", "green", "purple", "blue", "TRUred"]',
:class='{active: user.preferences.hair.color === option, locked: !user.purchased.hair.color || !user.purchased.hair.color[option]}')
.color-bangs.sprite.customize-option(:class="`hair_bangs_1_${option}`", @click='user.purchased.hair.color && user.purchased.hair.color[option] ? set({"preferences.hair.color": option}) : unlock(`skin.${option}`)')
.gem-lock(v-if='!user.purchased.hair.color || !user.purchased.hair.color[option]')
.option(v-for='option in premiumHairColors',
:class='{active: option.active === option, locked: option.locked}')
.color-bangs.sprite.customize-option(:class="`hair_bangs_1_${option.key}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", premiumHairColorKeys, "color")', @click='unlock(`hair.color.${premiumHairColorKeys.join(",hair.color.")}`)') $t('purchaseAll')
#style.row(v-if='activeSubPage === "style"')
.col-12.customize-options(v-if='editing')
.option(v-for='option in baseHair3',
:class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_base_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair3Keys, "base")', @click='unlock(`hair.base.${baseHair3Keys.join(",hair.base.")}`)') $t('purchaseAll')
.col-12.customize-options(v-if='editing')
.option(v-for='option in baseHair4',
:class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_base_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair4Keys, "base")', @click='unlock(`hair.base.${baseHair4Keys.join(",hair.base.")}`)') $t('purchaseAll')
#bangs.row(v-if='activeSubPage === "bangs"')
.col-12.customize-options
.head_0.option(@click='set({"preferences.hair.bangs": 0})',
@@ -118,46 +144,38 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
#base-hair.row(v-if='activeSubPage === "ponytail"')
.col-12.customize-options
.head_0.option(@click='set({"preferences.hair.base": 0})', :class="[{ active: user.preferences.hair.base === 0 }, 'hair_base_0_' + user.preferences.hair.color]")
.option(v-for='option in ["1", "3"]',
.option(v-for='option in baseHair1',
:class='{active: user.preferences.hair.base === option}')
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["2", "4", "5", "6", "7", "8"]',
:class='{active: user.preferences.hair.base === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}')
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]')
.option(v-for='option in baseHair2',
:class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_base_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair2Keys, "base")', @click='unlock(`hair.base.${baseHair2Keys.join(",hair.base.")}`)') $t('purchaseAll')
#facialhair.row(v-if='activeSubPage === "facialhair"')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["9", "10", "11", "12", "13", "14"]',
:class='{active: user.preferences.hair.base === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}')
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]')
.option(v-for='option in baseHair5',
:class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_beard_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair5Keys, "beard")', @click='unlock(`hair.beard.${baseHair5Keys.join(",hair.beard.")}`)') $t('purchaseAll')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["15", "16", "17", "18", "19", "20"]',
:class='{active: user.preferences.hair.base === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}')
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]')
.option(v-for='option in baseHair6',
:class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_mustache_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["1", "2", "3"]',
:class='{active: user.preferences.hair.beard === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}')
.base.sprite.customize-option(:class="`hair_beard_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.beard": option})')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["1", "2"]',
:class='{active: user.preferences.hair.mustache === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}')
.base.sprite.customize-option(:class="`hair_mustache_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.mustache": option})')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]')
.svg-icon.gem(v-html='icons.gem')
span 2
.section.container.customize-section(v-if='activeTopPage === "extra"')
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair6Keys, "mustache")', @click='unlock(`hair.mustache.${baseHair6Keys.join(",hair.mustache.")}`)') $t('purchaseAll')
#extra.section.container.customize-section(v-if='activeTopPage === "extra"')
.row.sub-menu.col-6.offset-3.text-center
.col-4.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}')
strong(v-once) {{$t('glasses')}}
@@ -175,13 +193,14 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
.eyewear_special_whiteTopFrame.option(@click='equip("eyewear_special_whiteTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_whiteTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_whiteTopFrame"}')
.eyewear_special_yellowTopFrame.option(@click='equip("eyewear_special_yellowTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_yellowTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_yellowTopFrame"}')
#animal-ears.col-12.customize-options(v-if='editing')
.option(v-for='option in ["bearEars", "cactusEars", "foxEars", "lionEars", "pandaEars", "pigEars", "tigerEars", "wolfEars"]',
:class='[{active: user.preferences.costume ? user.items.gear.costume.headAccessory === `headAccessory_special_${option}` : user.items.gear.equipped.headAccessory === `headAccessory_special_${option}`}, {locked: !user.purchased.headAccessory || !user.purchased.headAccessory[option]}]')
.sprite.customize-option(:class="`headAccessory_special_${option}`", @click='equip(`headAccessory_special_${option}`)')
.gem-lock(v-if='!user.purchased.headAccessory || !user.purchased.headAccessory[option]')
.option(v-for='option in animalEars',
:class='{active: option.active, locked: option.locked}')
.sprite.customize-option(:class="`headAccessory_special_${option.key}`", @click='option.click')
.gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem')
span 2
.col-12.text-center
button.btn.btn-secondary.purchase-all(v-if='!animalEarsOwned', @click='unlock(animalEarsUnlockString)') $t('purchaseAll')
#wheelchairs.row(v-if='activeSubPage === "wheelchair"')
.col-12.customize-options.weelchairs
.option(@click='set({"preferences.chair": "none"})', :class='{active: user.preferences.chair === "none"}')
@@ -202,7 +221,6 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter',
popover-placement='right', popover-append-to-body='true',
ng-click='user.items.gear.owned[item.key] ? equip(item.key) : purchase(item.type,item)')
#backgrounds.section.container.customize-section(v-if='activeTopPage === "backgrounds"')
.row.col-12.text-center.set-title
strong {{backgroundShopSets[0].text}}
@@ -359,6 +377,10 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
position: relative;
}
.purchase-all {
margin-bottom: 1em;
}
.section {
margin-top: 2em;
}
@@ -892,18 +914,26 @@ export default {
},
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);
},
data () {
let backgroundShopSets = getBackgroundShopSets();
return {
loading: false,
backgroundShopSets,
backgroundUpdate: new Date(),
specialShirts: ['convict', 'cross', 'fire', 'horizon', 'ocean', 'purple', 'rainbow', 'redblue', 'thunder', 'tropical', 'zombie'],
specialShirtKeys: ['convict', 'cross', 'fire', 'horizon', 'ocean', 'purple', 'rainbow', 'redblue', 'thunder', 'tropical', 'zombie'],
rainbowSkinKeys: ['eb052b', 'f69922', 'f5d70f', '0ff591', '2b43f6', 'd7a9f7', '800ed0', 'rainbow'],
animalSkinKeys: ['bear', 'cactus', 'fox', 'lion', 'panda', 'pig', 'tiger', 'wolf'],
premiumHairColorKeys: ['rainbow', 'yellow', 'green', 'purple', 'blue', 'TRUred'],
baseHair1: ['1', '3'],
baseHair2Keys: ['2', '4', '5', '6', '7', '8'],
baseHair3Keys: ['9', '10', '11', '12', '13', '14'],
baseHair4Keys: ['15', '16', '17', '18', '19', '20'],
baseHair5Keys: ['1', '2', '3'],
baseHair6Keys: ['1', '2'],
animalEarsKeys: ['bearEars', 'cactusEars', 'foxEars', 'lionEars', 'pandaEars', 'pigEars', 'tigerEars', 'wolfEars'],
icons: Object.freeze({
logoPurple,
bodyIcon,
@@ -934,6 +964,125 @@ export default {
},
computed: {
...mapState({user: 'user.data'}),
animalEarsUnlockString () {
let animalItemKeys = this.animalEarsKeys.map(key => {
return `items.gear.owned.headAccessory_special_${key}`;
});
return animalItemKeys.join(',');
},
animalEarsOwned () {
// @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 own = true;
this.animalEarsKeys.forEach(key => {
if (!this.user.items.gear.owned[`headAccessory_special_${key}`]) own = false;
});
return own;
},
animalEars () {
// @TODO: This is not like other purchase items
// @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.animalEarsKeys;
let options = keys.map(key => {
let newKey = `headAccessory_special_${key}`;
let userPurchased = this.user.items.gear.owned[newKey];
let locked = !userPurchased;
let 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.locked = locked;
option.click = () => {
return locked ? this.purchase('gear', newKey) : this.equip(newKey);
};
return option;
});
return options;
},
specialShirts () {
// @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.specialShirtKeys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'shirt');
});
return options;
},
rainbowSkins () {
// @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.rainbowSkinKeys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'skin');
});
return options;
},
animalSkins () {
// @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.animalSkinKeys;
let options = keys.map(key => {
return this.mapKeysToOption(key, 'skin');
});
return options;
},
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');
});
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');
});
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 => {
return this.mapKeysToOption(key, 'hair', 'base');
});
return options;
},
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');
});
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', 'beard');
});
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', 'mustache');
});
return options;
},
editing () {
return this.$store.state.avatarEditorOptions.editingUser;
},
@@ -968,6 +1117,41 @@ export default {
},
},
methods: {
purchase (type, key) {
this.$store.dispatch('shops:purchase', {
type,
key,
});
this.backgroundUpdate = new Date();
},
mapKeysToOption (key, type, subType) {
let userPreference = subType ? this.user.preferences[type][subType] : this.user.preferences[type];
let userPurchased = subType ? this.user.purchased[type][subType] : this.user.purchased[type];
let locked = !userPurchased || !userPurchased[key];
let pathKey = subType ? `${type}.${subType}` : `${type}`;
let option = {};
option.key = key;
option.active = userPreference === key;
option.locked = locked;
option.click = () => {
return locked ? this.unlock(`${pathKey}.${key}`) : this.set({[`preferences.${pathKey}`]: key});
};
return option;
},
userOwnsSet (type, setKeys, subType) {
let owns = true;
setKeys.forEach(key => {
if (subType) {
if (!this.user.purchased[type] || !this.user.purchased[type][subType] || !this.user.purchased[type][subType][key]) owns = false;
return;
}
if (!this.user.purchased[type][key]) owns = false;
});
return owns;
},
prev () {
this.modalPage -= 1;
},

View File

@@ -118,6 +118,7 @@ export default {
let guilds = await this.$store.dispatch('guilds:getPublicGuilds', this.queryFilters);
guilds.forEach((guild) => {
if (!guild.categories) return;
guild.categorySlugs = guild.categories.map(cat => {
return cat.slug;
});

View File

@@ -1,9 +1,20 @@
<template lang="pug">
b-modal#private-message(title="Message", size='sm', :hide-footer="true")
textarea.form-control(v-model='privateMessage')
button.btn.btn-primary(@click='sendPrivateMessage()') Send
b-modal#private-message(title="Message", size='md', :hide-footer="true")
.content
textarea.form-control(v-model='privateMessage')
button.btn.btn-primary(@click='sendPrivateMessage()', :disabled='loading') Send
</template>
<style lang="scss" scoped>
.content {
padding: 1em;
textarea {
margin-bottom: 1em;
}
}
</style>
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
import notifications from 'client/mixins/notifications';
@@ -17,17 +28,22 @@ export default {
data () {
return {
privateMessage: '',
loading: false,
};
},
methods: {
async sendPrivateMessage () {
if (!this.privateMessage || !this.userIdToMessage) return;
this.loading = true;
await this.$store.dispatch('members:sendPrivateMessage', {
message: this.privateMessage,
toUserId: this.userIdToMessage,
});
this.loading = false;
this.text(this.$t('messageSentAlert'));
},
},

View File

@@ -23,11 +23,11 @@
.strike
span OR
.form
input.form-control(type='text', placeholder='Username', v-model='username')
input.form-control(type='email', placeholder='Email', v-model='email')
input.form-control(type='password', placeholder='Password', v-model='password')
input.form-control(type='password', placeholder='Confirm Password', v-model='passwordConfirm')
p By clicking the button below, you are indicating that you have read and agree to the Terms of Service and Privacy Policy.
input.form-control(type='text', placeholder='Username', v-model='username', :class='{"input-valid": username.length > 0}')
input.form-control(type='email', placeholder='Email', v-model='email', :class='{"input-invalid": emailInvalid, "input-valid": emailValid}')
input.form-control(type='password', placeholder='Password', v-model='password', :class='{"input-valid": password.length > 0}')
input.form-control(type='password', placeholder='Confirm Password', v-model='passwordConfirm', :class='{"input-invalid": passwordConfirmInvalid, "input-valid": passwordConfirmValid}')
p.form-text(v-once, v-html="$t('termsAndAgreement')")
button.sign-up(@click='register()') Sign Up
.col-12
.spacer.svg-icon(v-html='icons.spacer')
@@ -98,12 +98,10 @@
h3.col-12 Join over 2,000,000 people having fun while accomplishing their goals!
.row
.col-12.text-center
button.btn.btn-primary(@click='playButtonClick()') Join Habitica Today
button.btn.btn-primary.join-button(@click='playButtonClick()') Join Habitica Today
.row.featured
.col-12.text-center
strong Featured in
.container-fluid
.seamless_stars_varied_opacity_repeat
.container-fluid.featured
.row
.col-12
@@ -111,10 +109,12 @@
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/nyt-logo.png', alt="$t(altAttrNewYorkTimes)")
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/makeuseof.png', alt="$t(altAttrMakeUseOf)")
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/Forbes_logo.png', alt="$t(altAttrForbes)")
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/Cnetlogo.png', alt="$t(altAttrCnet)")
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/Fast-Company-logo.png', alt="$t(altAttrFastCompany)")
.cnet.svg-icon(v-html='icons.cnet')
.fast-company.svg-icon(v-html='icons.fastCompany')
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/kickstarter-logo.png', alt="$t(altAttrKickstarter)")
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/discover-logo.png', alt="$t(altAttrDiscover)")
.container-fluid
.seamless_stars_varied_opacity_repeat
#bottom-wrap.purple-4
#bottom-background
@@ -122,6 +122,34 @@
.midground_foreground_extended2
</template>
<style lang="scss">
.form-text a {
color: #fff !important;
}
#purple-footer {
background-color: #271b3d;
footer, footer a {
background: transparent;
color: #d5c8ff;
}
.logo {
color: #bda8ff;
}
.social-circle, .btn-donate {
background: #36205d;
color: #bda8ff;
.svg-icon {
color: #bda8ff;
}
}
}
</style>
<style lang="scss" scoped>
@import '~client/assets/scss/static.scss';
@@ -270,6 +298,11 @@
color: $purple-400;
}
input:focus {
border: solid 2px #9a62ff;
color: #fff;
}
button.sign-up {
width: 100%;
height: 48px;
@@ -280,6 +313,12 @@
font-size: 16px;
}
.sign-up:hover {
background-color: #50b5e9;
box-shadow: 0 4px 4px 0 rgba(26, 24, 29, 0.16), 0 1px 8px 0 rgba(26, 24, 29, 0.12);
cursor: pointer;
}
::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: $purple-400;
}
@@ -336,6 +375,10 @@
margin-right: .5em;
}
.app {
cursor: pointer;
}
.iphones {
width: 436px
}
@@ -372,6 +415,12 @@
padding-bottom: 5em;
}
.join-button:hover {
cursor: pointer;
background-color: #b288ff;
box-shadow: 0 4px 4px 0 rgba(26, 24, 29, 0.16), 0 1px 8px 0 rgba(26, 24, 29, 0.12);
}
.featured .row {
margin-top: 0;
}
@@ -379,6 +428,26 @@
.featured {
text-align: center;
.svg-icon {
max-height: 30px;
max-width: 120px;
color: #fff;
display: inline-block;
}
.cnet {
width: 40px;
height: 40px;
padding-top: .5em;
margin-right: 1em;
}
.fast-company {
width: 161.3px;
height: 24px;
padding-top: .8em;
}
img {
max-height: 30px;
max-width: 120px;
@@ -440,6 +509,8 @@
import pixelHorizontal3 from 'assets/images/home/pixel-horizontal-3.svg';
import facebookSquareIcon from 'assets/svg/facebook-square.svg';
import googleIcon from 'assets/svg/google.svg';
import cnet from 'assets/svg/cnet.svg';
import fastCompany from 'assets/svg/fast-company.svg';
import * as Analytics from 'client/libs/analytics';
export default {
@@ -455,6 +526,8 @@
pixelHorizontal3,
facebookIcon: facebookSquareIcon,
googleIcon,
cnet,
fastCompany,
}),
userCount: 1000000,
username: '',
@@ -477,7 +550,29 @@
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line
});
},
computed: {
emailValid () {
if (this.email.length === 0) return false;
return this.validateEmail(this.email);
},
emailInvalid () {
if (this.email.length === 0) return false;
return !this.validateEmail(this.email);
},
passwordConfirmValid () {
if (this.passwordConfirm.length === 0) return false;
return this.passwordConfirm === this.password;
},
passwordConfirmInvalid () {
if (this.passwordConfirm.length === 0) return false;
return this.passwordConfirm !== this.password;
},
},
methods: {
validateEmail (email) {
let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
},
async register () {
if (this.password !== this.passwordConfirm) {
alert('Passwords must match');

View File

@@ -547,7 +547,7 @@ export default {
weekdaysMin (dayNumber) {
return moment.weekdaysMin(dayNumber);
},
submit () {
async submit () {
if (this.newChecklistItem) this.addChecklistItem();
if (this.purpose === 'create') {
@@ -558,10 +558,21 @@ export default {
});
this.$emit('taskCreated', this.task);
} else if (this.groupId) {
this.$store.dispatch('tasks:createGroupTasks', {
await this.$store.dispatch('tasks:createGroupTasks', {
groupId: this.groupId,
tasks: [this.task],
});
let promises = this.assignedMembers.map(memberId => {
return this.$store.dispatch('tasks:assignTask', {
taskId: this.task._id,
userId: memberId,
});
});
Promise.all(promises);
this.task.group.assignedUsers = this.assignedMembers;
this.$emit('taskCreated', this.task);
} else {
this.createTask(this.task);
@@ -596,13 +607,24 @@ export default {
this.requiresApproval = truthy;
},
async toggleAssignment (memberId) {
if (this.assignedMembers.indexOf(memberId) === -1) {
let assignedIndex = this.assignedMembers.indexOf(memberId);
if (assignedIndex === -1) {
if (this.purpose === 'create') {
return;
}
await this.$store.dispatch('tasks:unassignTask', {
taskId: this.task._id,
userId: this.user._id,
});
return;
}
if (this.purpose === 'create') {
return;
}
await this.$store.dispatch('tasks:assignTask', {
taskId: this.task._id,
userId: this.user._id,

View File

@@ -189,5 +189,7 @@
"hideQuickAllocation": "Hide stat allocation",
"quickAllocationLevelPopover": "Each level earns you one point to assign to an attribute of your choice. You can do so manually, or let the game decide for you using one of the Automatic Allocation options found in User -> Stats.",
"invalidAttribute": "\"<%= attr %>\" is not a valid attribute.",
"notEnoughAttrPoints": "You don't have enough attribute points."
"notEnoughAttrPoints": "You don't have enough attribute points.",
"style": "Style",
"facialhair": "Facial"
}

View File

@@ -198,5 +198,6 @@
"subscriptionBenefit4": "Unique cosmetic items for your avatar each month.",
"subscriptionBenefit5": "Receive the exclusive Royal Purple Jackalope pet!",
"subscriptionBenefit6": "Earn Mystic Hourglasses for use in the Time Travelers' Shop!",
"haveCouponCode": "Do you have a coupon code?"
"haveCouponCode": "Do you have a coupon code?",
"purchaseAll": "Purchase All"
}