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 { #bottom-wrap {
margin-top: 6em; margin-top: 6em;
position: fixed;
width: 100%;
bottom: 0;
} }
#bottom-background { #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 // @TODO Implement in V2 .section.row
.col-12.text-center .col-12.text-center
button.btn.btn-secondary(v-once) {{$t('randomize')}} button.btn.btn-secondary(v-once) {{$t('randomize')}}
.container.section.text-center.customize-menu #options-nav.container.section.text-center.customize-menu
.row .row
div(:class='{"col-3": !editing, "col-2 offset-1": editing}') div(:class='{"col-3": !editing, "col-2 offset-1": editing}')
.menu-item(@click='changeTopPage("body", "size")') .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")') .menu-item(@click='changeTopPage("backgrounds", "2017")')
.svg-icon(v-html='icons.backgroundsIcon') .svg-icon(v-html='icons.backgroundsIcon')
strong(v-once) {{$t('backgrounds')}} strong(v-once) {{$t('backgrounds')}}
#body.section.customize-section(v-if='activeTopPage === "body"')
.section.customize-section(v-if='activeTopPage === "body"')
.row.sub-menu.col-6.offset-3.text-center .row.sub-menu.col-6.offset-3.text-center
.col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}') .col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}')
strong(v-once) {{$t('size')}} strong(v-once) {{$t('size')}}
@@ -53,16 +52,15 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
:class='{active: user.preferences.shirt === option}') :class='{active: user.preferences.shirt === option}')
.sprite.customize-option(:class="`slim_shirt_${option}`", @click='set({"preferences.shirt": option})') .sprite.customize-option(:class="`slim_shirt_${option}`", @click='set({"preferences.shirt": option})')
.col-12.customize-options(v-if='editing') .col-12.customize-options(v-if='editing')
.option(v-for='option in specialShirts', .option(v-for='item in specialShirts',
:class='{active: user.preferences.shirt === option, locked: !user.purchased.shirt[option]}') :class='{active: item.active, locked: item.locked}')
.sprite.customize-option(:class="`broad_shirt_${option}`", @click='user.purchased.shirt[option] ? set({"preferences.shirt": option}) : unlock(`shirt.${option}`)') .sprite.customize-option(:class="`broad_shirt_${item.key}`", @click='item.click')
.gem-lock(v-if='!user.purchased.shirt[option]') .gem-lock(v-if='item.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 span 2
.col-12.text-center .col-12.text-center
button.btn.btn-secondary(@click='unlock(`shirt.${specialShirts.join(",shirt.")}`)') Purchase All 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"')
.section.customize-section(v-if='activeTopPage === "skin"')
.row.sub-menu.col-6.offset-3.text-center .row.sub-menu.col-6.offset-3.text-center
.col-6.offset-3.text-center.sub-menu-item(:class='{active: activeSubPage === "color"}') .col-6.offset-3.text-center.sub-menu-item(:class='{active: activeSubPage === "color"}')
strong(v-once) {{$t('color')}} strong(v-once) {{$t('color')}}
@@ -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})') .skin.sprite.customize-option(:class="`skin_${option}`", @click='set({"preferences.skin": option})')
.row(v-if='editing') .row(v-if='editing')
.col-12.customize-options .col-12.customize-options
.option(v-for='option in ["eb052b", "f69922", "f5d70f", "0ff591", "2b43f6", "d7a9f7", "800ed0", "rainbow"]', .option(v-for='option in rainbowSkins',
:class='{active: user.preferences.skin === option, locked: !user.purchased.skin[option]}') :class='{active: option.active, locked: option.locked}')
.skin.sprite.customize-option(:class="`skin_${option}`", @click='user.purchased.skin[option] ? set({"preferences.skin": option}) : unlock(`skin.${option}`)') .skin.sprite.customize-option(:class="`skin_${option.key}`", @click='option.click')
.gem-lock(v-if='!user.purchased.skin[option]') .gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 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') .row(v-if='editing')
.col-12.customize-options .col-12.customize-options
.option(v-for='option in ["bear", "cactus", "fox", "lion", "panda", "pig", "tiger", "wolf"]', .option(v-for='option in animalSkins',
:class='{active: user.preferences.skin === option, locked: !user.purchased.skin[option]}') :class='{active: option.active, locked: option.locked}')
.skin.sprite.customize-option(:class="`skin_${option}`", @click='user.purchased.skin[option] ? set({"preferences.skin": option}) : unlock(`skin.${option}`)') .skin.sprite.customize-option(:class="`skin_${option.key}`", @click='option.click')
.gem-lock(v-if='!user.purchased.skin[option]') .gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 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"') #hair.section.customize-section(v-if='activeTopPage === "hair"')
.row.sub-menu.col-6.offset-3.text-center .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')}} 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"}') .col-2.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}')
strong(v-once) {{$t('bangs')}} strong(v-once) {{$t('bangs')}}
.col-3.text-center.sub-menu-item(@click='changeSubPage("ponytail")', :class='{active: activeSubPage === "ponytail"}') .col-3.text-center.sub-menu-item(@click='changeSubPage("ponytail")', :class='{active: activeSubPage === "ponytail"}')
strong(v-once) {{$t('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 .col-12.customize-options
.option(v-for='option in ["white", "brown", "blond", "red", "black"]', .option(v-for='option in ["white", "brown", "blond", "red", "black"]',
:class='{active: user.preferences.hair.color === option}') :class='{active: user.preferences.hair.color === option}')
.color-bangs.sprite.customize-option(:class="`hair_bangs_1_${option}`", @click='set({"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') .col-12.customize-options(v-if='editing')
.option(v-for='option in ["rainbow", "yellow", "green", "purple", "blue", "TRUred"]', .option(v-for='option in premiumHairColors',
:class='{active: user.preferences.hair.color === option, locked: !user.purchased.hair.color || !user.purchased.hair.color[option]}') :class='{active: option.active === option, locked: option.locked}')
.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}`)') .color-bangs.sprite.customize-option(:class="`hair_bangs_1_${option.key}`", @click='option.click')
.gem-lock(v-if='!user.purchased.hair.color || !user.purchased.hair.color[option]') .gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 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"') #bangs.row(v-if='activeSubPage === "bangs"')
.col-12.customize-options .col-12.customize-options
.head_0.option(@click='set({"preferences.hair.bangs": 0})', .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"') #base-hair.row(v-if='activeSubPage === "ponytail"')
.col-12.customize-options .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]") .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}') :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})') .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') .col-12.customize-options(v-if='editing')
.option(v-for='option in ["2", "4", "5", "6", "7", "8"]', .option(v-for='option in baseHair2',
:class='{active: user.preferences.hair.base === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}') :class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})') .base.sprite.customize-option(:class="`hair_base_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]') .gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 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') .col-12.customize-options(v-if='editing')
.option(v-for='option in ["9", "10", "11", "12", "13", "14"]', .option(v-for='option in baseHair5',
:class='{active: user.preferences.hair.base === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}') :class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})') .base.sprite.customize-option(:class="`hair_beard_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]') .gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 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') .col-12.customize-options(v-if='editing')
.option(v-for='option in ["15", "16", "17", "18", "19", "20"]', .option(v-for='option in baseHair6',
:class='{active: user.preferences.hair.base === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}') :class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})') .base.sprite.customize-option(:class="`hair_mustache_${option.key}_${user.preferences.hair.color}`", @click='option.click')
.gem-lock(v-if='!user.purchased.hair.base || !user.purchased.hair.base[option]') .gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 span 2
.col-12.customize-options(v-if='editing') .col-12.text-center
.option(v-for='option in ["1", "2", "3"]', button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair6Keys, "mustache")', @click='unlock(`hair.mustache.${baseHair6Keys.join(",hair.mustache.")}`)') $t('purchaseAll')
:class='{active: user.preferences.hair.beard === option, locked: !user.purchased.hair.base || !user.purchased.hair.base[option]}') #extra.section.container.customize-section(v-if='activeTopPage === "extra"')
.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"')
.row.sub-menu.col-6.offset-3.text-center .row.sub-menu.col-6.offset-3.text-center
.col-4.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}') .col-4.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}')
strong(v-once) {{$t('glasses')}} strong(v-once) {{$t('glasses')}}
@@ -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_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"}') .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') #animal-ears.col-12.customize-options(v-if='editing')
.option(v-for='option in ["bearEars", "cactusEars", "foxEars", "lionEars", "pandaEars", "pigEars", "tigerEars", "wolfEars"]', .option(v-for='option in animalEars',
: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]}]') :class='{active: option.active, locked: option.locked}')
.sprite.customize-option(:class="`headAccessory_special_${option}`", @click='equip(`headAccessory_special_${option}`)') .sprite.customize-option(:class="`headAccessory_special_${option.key}`", @click='option.click')
.gem-lock(v-if='!user.purchased.headAccessory || !user.purchased.headAccessory[option]') .gem-lock(v-if='option.locked')
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span 2 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"') #wheelchairs.row(v-if='activeSubPage === "wheelchair"')
.col-12.customize-options.weelchairs .col-12.customize-options.weelchairs
.option(@click='set({"preferences.chair": "none"})', :class='{active: user.preferences.chair === "none"}') .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='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter',
popover-placement='right', popover-append-to-body='true', popover-placement='right', popover-append-to-body='true',
ng-click='user.items.gear.owned[item.key] ? equip(item.key) : purchase(item.type,item)') ng-click='user.items.gear.owned[item.key] ? equip(item.key) : purchase(item.type,item)')
#backgrounds.section.container.customize-section(v-if='activeTopPage === "backgrounds"') #backgrounds.section.container.customize-section(v-if='activeTopPage === "backgrounds"')
.row.col-12.text-center.set-title .row.col-12.text-center.set-title
strong {{backgroundShopSets[0].text}} strong {{backgroundShopSets[0].text}}
@@ -359,6 +377,10 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
position: relative; position: relative;
} }
.purchase-all {
margin-bottom: 1em;
}
.section { .section {
margin-top: 2em; margin-top: 2em;
} }
@@ -892,18 +914,26 @@ export default {
}, },
mounted () { mounted () {
if (this.editing) this.modalPage = 2; if (this.editing) this.modalPage = 2;
// Buy modal is global, so we listen at root. I'd like to not // Buy modal is global, so we listen at root. I'd like to not
this.$root.$on('buyModal::boughtItem', this.backgroundPurchased); this.$root.$on('buyModal::boughtItem', this.backgroundPurchased);
}, },
data () { data () {
let backgroundShopSets = getBackgroundShopSets(); let backgroundShopSets = getBackgroundShopSets();
return { return {
loading: false, loading: false,
backgroundShopSets, backgroundShopSets,
backgroundUpdate: new Date(), 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({ icons: Object.freeze({
logoPurple, logoPurple,
bodyIcon, bodyIcon,
@@ -934,6 +964,125 @@ export default {
}, },
computed: { computed: {
...mapState({user: 'user.data'}), ...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 () { editing () {
return this.$store.state.avatarEditorOptions.editingUser; return this.$store.state.avatarEditorOptions.editingUser;
}, },
@@ -968,6 +1117,41 @@ export default {
}, },
}, },
methods: { 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 () { prev () {
this.modalPage -= 1; this.modalPage -= 1;
}, },

View File

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

View File

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

View File

@@ -23,11 +23,11 @@
.strike .strike
span OR span OR
.form .form
input.form-control(type='text', placeholder='Username', v-model='username') 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') 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') 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') input.form-control(type='password', placeholder='Confirm Password', v-model='passwordConfirm', :class='{"input-invalid": passwordConfirmInvalid, "input-valid": passwordConfirmValid}')
p By clicking the button below, you are indicating that you have read and agree to the Terms of Service and Privacy Policy. p.form-text(v-once, v-html="$t('termsAndAgreement')")
button.sign-up(@click='register()') Sign Up button.sign-up(@click='register()') Sign Up
.col-12 .col-12
.spacer.svg-icon(v-html='icons.spacer') .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! h3.col-12 Join over 2,000,000 people having fun while accomplishing their goals!
.row .row
.col-12.text-center .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 .row.featured
.col-12.text-center .col-12.text-center
strong Featured in strong Featured in
.container-fluid
.seamless_stars_varied_opacity_repeat
.container-fluid.featured .container-fluid.featured
.row .row
.col-12 .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/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/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/Forbes_logo.png', alt="$t(altAttrForbes)")
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/Cnetlogo.png', alt="$t(altAttrCnet)") .cnet.svg-icon(v-html='icons.cnet')
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/Fast-Company-logo.png', alt="$t(altAttrFastCompany)") .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/kickstarter-logo.png', alt="$t(altAttrKickstarter)")
img(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/presslogos/discover-logo.png', alt="$t(altAttrDiscover)") 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-wrap.purple-4
#bottom-background #bottom-background
@@ -122,6 +122,34 @@
.midground_foreground_extended2 .midground_foreground_extended2
</template> </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> <style lang="scss" scoped>
@import '~client/assets/scss/static.scss'; @import '~client/assets/scss/static.scss';
@@ -270,6 +298,11 @@
color: $purple-400; color: $purple-400;
} }
input:focus {
border: solid 2px #9a62ff;
color: #fff;
}
button.sign-up { button.sign-up {
width: 100%; width: 100%;
height: 48px; height: 48px;
@@ -280,6 +313,12 @@
font-size: 16px; 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 */ ::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: $purple-400; color: $purple-400;
} }
@@ -336,6 +375,10 @@
margin-right: .5em; margin-right: .5em;
} }
.app {
cursor: pointer;
}
.iphones { .iphones {
width: 436px width: 436px
} }
@@ -372,6 +415,12 @@
padding-bottom: 5em; 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 { .featured .row {
margin-top: 0; margin-top: 0;
} }
@@ -379,6 +428,26 @@
.featured { .featured {
text-align: center; 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 { img {
max-height: 30px; max-height: 30px;
max-width: 120px; max-width: 120px;
@@ -440,6 +509,8 @@
import pixelHorizontal3 from 'assets/images/home/pixel-horizontal-3.svg'; import pixelHorizontal3 from 'assets/images/home/pixel-horizontal-3.svg';
import facebookSquareIcon from 'assets/svg/facebook-square.svg'; import facebookSquareIcon from 'assets/svg/facebook-square.svg';
import googleIcon from 'assets/svg/google.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'; import * as Analytics from 'client/libs/analytics';
export default { export default {
@@ -455,6 +526,8 @@
pixelHorizontal3, pixelHorizontal3,
facebookIcon: facebookSquareIcon, facebookIcon: facebookSquareIcon,
googleIcon, googleIcon,
cnet,
fastCompany,
}), }),
userCount: 1000000, userCount: 1000000,
username: '', username: '',
@@ -477,7 +550,29 @@
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line 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: { 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 () { async register () {
if (this.password !== this.passwordConfirm) { if (this.password !== this.passwordConfirm) {
alert('Passwords must match'); alert('Passwords must match');

View File

@@ -158,7 +158,7 @@
input.custom-control-input(type="checkbox", :value="member._id", v-model="assignedMembers", @change='toggleAssignment(member._id)') input.custom-control-input(type="checkbox", :value="member._id", v-model="assignedMembers", @change='toggleAssignment(member._id)')
span.custom-control-indicator span.custom-control-indicator
span.custom-control-description(v-once) {{ member.profile.name }} span.custom-control-description(v-once) {{ member.profile.name }}
.row .row
button.btn.btn-primary(@click="showAssignedSelect = !showAssignedSelect") {{$t('close')}} button.btn.btn-primary(@click="showAssignedSelect = !showAssignedSelect") {{$t('close')}}
@@ -547,7 +547,7 @@ export default {
weekdaysMin (dayNumber) { weekdaysMin (dayNumber) {
return moment.weekdaysMin(dayNumber); return moment.weekdaysMin(dayNumber);
}, },
submit () { async submit () {
if (this.newChecklistItem) this.addChecklistItem(); if (this.newChecklistItem) this.addChecklistItem();
if (this.purpose === 'create') { if (this.purpose === 'create') {
@@ -558,10 +558,21 @@ export default {
}); });
this.$emit('taskCreated', this.task); this.$emit('taskCreated', this.task);
} else if (this.groupId) { } else if (this.groupId) {
this.$store.dispatch('tasks:createGroupTasks', { await this.$store.dispatch('tasks:createGroupTasks', {
groupId: this.groupId, groupId: this.groupId,
tasks: [this.task], 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); this.$emit('taskCreated', this.task);
} else { } else {
this.createTask(this.task); this.createTask(this.task);
@@ -596,13 +607,24 @@ export default {
this.requiresApproval = truthy; this.requiresApproval = truthy;
}, },
async toggleAssignment (memberId) { 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', { await this.$store.dispatch('tasks:unassignTask', {
taskId: this.task._id, taskId: this.task._id,
userId: this.user._id, userId: this.user._id,
}); });
return; return;
} }
if (this.purpose === 'create') {
return;
}
await this.$store.dispatch('tasks:assignTask', { await this.$store.dispatch('tasks:assignTask', {
taskId: this.task._id, taskId: this.task._id,
userId: this.user._id, userId: this.user._id,

View File

@@ -189,5 +189,7 @@
"hideQuickAllocation": "Hide stat allocation", "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.", "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.", "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.", "subscriptionBenefit4": "Unique cosmetic items for your avatar each month.",
"subscriptionBenefit5": "Receive the exclusive Royal Purple Jackalope pet!", "subscriptionBenefit5": "Receive the exclusive Royal Purple Jackalope pet!",
"subscriptionBenefit6": "Earn Mystic Hourglasses for use in the Time Travelers' Shop!", "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"
} }