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
+3
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

@@ -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

@@ -184,6 +184,9 @@
#bottom-wrap {
margin-top: 6em;
position: fixed;
width: 100%;
bottom: 0;
}
#bottom-background {
+248 -64
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;
},
@@ -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;
});
@@ -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'));
},
},
+105 -10
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');
+26 -4
View File
@@ -158,7 +158,7 @@
input.custom-control-input(type="checkbox", :value="member._id", v-model="assignedMembers", @change='toggleAssignment(member._id)')
span.custom-control-indicator
span.custom-control-description(v-once) {{ member.profile.name }}
.row
button.btn.btn-primary(@click="showAssignedSelect = !showAssignedSelect") {{$t('close')}}
@@ -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,