diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2018-02-10 16:22:14 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2018-02-10 16:22:14 +0900 |
| commit | 4f1795b97b43e324d47653c5b172afa984446868 (patch) | |
| tree | c4dc6853e62297a284fa6bb9cbbdf4d7ab30d042 /src/web | |
| parent | wip (diff) | |
| download | misskey-4f1795b97b43e324d47653c5b172afa984446868.tar.gz misskey-4f1795b97b43e324d47653c5b172afa984446868.tar.bz2 misskey-4f1795b97b43e324d47653c5b172afa984446868.zip | |
wip
Diffstat (limited to 'src/web')
15 files changed, 561 insertions, 537 deletions
diff --git a/src/web/app/common/-tags/signin.tag b/src/web/app/common/-tags/signin.tag deleted file mode 100644 index 89213d1f73..0000000000 --- a/src/web/app/common/-tags/signin.tag +++ /dev/null @@ -1,155 +0,0 @@ -<mk-signin> - <form :class="{ signing: signing }" onsubmit={ onsubmit }> - <label class="user-name"> - <input ref="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="%i18n:common.tags.mk-signin.username%" autofocus="autofocus" required="required" oninput={ oninput }/>%fa:at% - </label> - <label class="password"> - <input ref="password" type="password" placeholder="%i18n:common.tags.mk-signin.password%" required="required"/>%fa:lock% - </label> - <label class="token" v-if="user && user.two_factor_enabled"> - <input ref="token" type="number" placeholder="%i18n:common.tags.mk-signin.token%" required="required"/>%fa:lock% - </label> - <button type="submit" disabled={ signing }>{ signing ? '%i18n:common.tags.mk-signin.signing-in%' : '%i18n:common.tags.mk-signin.signin%' }</button> - </form> - <style lang="stylus" scoped> - :scope - display block - - > form - display block - z-index 2 - - &.signing - &, * - cursor wait !important - - label - display block - margin 12px 0 - - [data-fa] - display block - pointer-events none - position absolute - bottom 0 - top 0 - left 0 - z-index 1 - margin auto - padding 0 16px - height 1em - color #898786 - - input[type=text] - input[type=password] - input[type=number] - user-select text - display inline-block - cursor auto - padding 0 0 0 38px - margin 0 - width 100% - line-height 44px - font-size 1em - color rgba(0, 0, 0, 0.7) - background #fff - outline none - border solid 1px #eee - border-radius 4px - - &:hover - background rgba(255, 255, 255, 0.7) - border-color #ddd - - & + i - color #797776 - - &:focus - background #fff - border-color #ccc - - & + i - color #797776 - - [type=submit] - cursor pointer - padding 16px - margin -6px 0 0 0 - width 100% - font-size 1.2em - color rgba(0, 0, 0, 0.5) - outline none - border none - border-radius 0 - background transparent - transition all .5s ease - - &:hover - color $theme-color - transition all .2s ease - - &:focus - color $theme-color - transition all .2s ease - - &:active - color darken($theme-color, 30%) - transition all .2s ease - - &:disabled - opacity 0.7 - - </style> - <script lang="typescript"> - this.mixin('api'); - - this.user = null; - this.signing = false; - - this.oninput = () => { - this.api('users/show', { - username: this.$refs.username.value - }).then(user => { - this.user = user; - this.$emit('user', user); - this.update(); - }); - }; - - this.onsubmit = e => { - e.preventDefault(); - - if (this.$refs.username.value == '') { - this.$refs.username.focus(); - return false; - } - if (this.$refs.password.value == '') { - this.$refs.password.focus(); - return false; - } - if (this.user && this.user.two_factor_enabled && this.$refs.token.value == '') { - this.$refs.token.focus(); - return false; - } - - this.update({ - signing: true - }); - - this.api('signin', { - username: this.$refs.username.value, - password: this.$refs.password.value, - token: this.user && this.user.two_factor_enabled ? this.$refs.token.value : undefined - }).then(() => { - location.reload(); - }).catch(() => { - alert('something happened'); - this.update({ - signing: false - }); - }); - - return false; - }; - </script> -</mk-signin> diff --git a/src/web/app/common/-tags/signup.tag b/src/web/app/common/-tags/signup.tag deleted file mode 100644 index 99be10609b..0000000000 --- a/src/web/app/common/-tags/signup.tag +++ /dev/null @@ -1,307 +0,0 @@ -<mk-signup> - <form onsubmit={ onsubmit } autocomplete="off"> - <label class="username"> - <p class="caption">%fa:at%%i18n:common.tags.mk-signup.username%</p> - <input ref="username" type="text" pattern="^[a-zA-Z0-9-]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required="required" onkeyup={ onChangeUsername }/> - <p class="profile-page-url-preview" v-if="refs.username.value != '' && username-state != 'invalidFormat' && username-state != 'minRange' && username-state != 'maxRange'">{ _URL_ + '/' + refs.username.value }</p> - <p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:common.tags.mk-signup.checking%</p> - <p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.available%</p> - <p class="info" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.unavailable%</p> - <p class="info" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.error%</p> - <p class="info" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.invalid-format%</p> - <p class="info" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.too-short%</p> - <p class="info" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.too-long%</p> - </label> - <label class="password"> - <p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%</p> - <input ref="password" type="password" placeholder="%i18n:common.tags.mk-signup.password-placeholder%" autocomplete="off" required="required" onkeyup={ onChangePassword }/> - <div class="meter" v-if="passwordStrength != ''" data-strength={ passwordStrength }> - <div class="value" ref="passwordMetar"></div> - </div> - <p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.weak-password%</p> - <p class="info" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.normal-password%</p> - <p class="info" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.strong-password%</p> - </label> - <label class="retype-password"> - <p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%(%i18n:common.tags.mk-signup.retype%)</p> - <input ref="passwordRetype" type="password" placeholder="%i18n:common.tags.mk-signup.retype-placeholder%" autocomplete="off" required="required" onkeyup={ onChangePasswordRetype }/> - <p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.password-matched%</p> - <p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.password-not-matched%</p> - </label> - <label class="recaptcha"> - <p class="caption"><template v-if="recaptchaed">%fa:toggle-on%</template><template v-if="!recaptchaed">%fa:toggle-off%</template>%i18n:common.tags.mk-signup.recaptcha%</p> - <div v-if="recaptcha" class="g-recaptcha" data-callback="onRecaptchaed" data-expired-callback="onRecaptchaExpired" data-sitekey={ recaptcha.site_key }></div> - </label> - <label class="agree-tou"> - <input name="agree-tou" type="checkbox" autocomplete="off" required="required"/> - <p><a href={ touUrl } target="_blank">利用規約</a>に同意する</p> - </label> - <button @click="onsubmit">%i18n:common.tags.mk-signup.create%</button> - </form> - <style lang="stylus" scoped> - :scope - display block - min-width 302px - overflow hidden - - > form - - label - display block - margin 16px 0 - - > .caption - margin 0 0 4px 0 - color #828888 - font-size 0.95em - - > [data-fa] - margin-right 0.25em - color #96adac - - > .info - display block - margin 4px 0 - font-size 0.8em - - > [data-fa] - margin-right 0.3em - - &.username - .profile-page-url-preview - display block - margin 4px 8px 0 4px - font-size 0.8em - color #888 - - &:empty - display none - - &:not(:empty) + .info - margin-top 0 - - &.password - .meter - display block - margin-top 8px - width 100% - height 8px - - &[data-strength=''] - display none - - &[data-strength='low'] - > .value - background #d73612 - - &[data-strength='medium'] - > .value - background #d7ca12 - - &[data-strength='high'] - > .value - background #61bb22 - - > .value - display block - width 0% - height 100% - background transparent - border-radius 4px - transition all 0.1s ease - - [type=text], [type=password] - user-select text - display inline-block - cursor auto - padding 0 12px - margin 0 - width 100% - line-height 44px - font-size 1em - color #333 !important - background #fff !important - outline none - border solid 1px rgba(0, 0, 0, 0.1) - border-radius 4px - box-shadow 0 0 0 114514px #fff inset - transition all .3s ease - - &:hover - border-color rgba(0, 0, 0, 0.2) - transition all .1s ease - - &:focus - color $theme-color !important - border-color $theme-color - box-shadow 0 0 0 1024px #fff inset, 0 0 0 4px rgba($theme-color, 10%) - transition all 0s ease - - &:disabled - opacity 0.5 - - .agree-tou - padding 4px - border-radius 4px - - &:hover - background #f4f4f4 - - &:active - background #eee - - &, * - cursor pointer - - p - display inline - color #555 - - button - margin 0 0 32px 0 - padding 16px - width 100% - font-size 1em - color #fff - background $theme-color - border-radius 3px - - &:hover - background lighten($theme-color, 5%) - - &:active - background darken($theme-color, 5%) - - </style> - <script lang="typescript"> - this.mixin('api'); - const getPasswordStrength = require('syuilo-password-strength'); - - this.usernameState = null; - this.passwordStrength = ''; - this.passwordRetypeState = null; - this.recaptchaed = false; - - this.aboutUrl = `${_DOCS_URL_}/${_LANG_}/tou`; - - window.onRecaptchaed = () => { - this.recaptchaed = true; - this.update(); - }; - - window.onRecaptchaExpired = () => { - this.recaptchaed = false; - this.update(); - }; - - this.on('mount', () => { - this.update({ - recaptcha: { - site_key: _RECAPTCHA_SITEKEY_ - } - }); - - const head = document.getElementsByTagName('head')[0]; - const script = document.createElement('script'); - script.setAttribute('src', 'https://www.google.com/recaptcha/api.js'); - head.appendChild(script); - }); - - this.onChangeUsername = () => { - const username = this.$refs.username.value; - - if (username == '') { - this.update({ - usernameState: null - }); - return; - } - - const err = - !username.match(/^[a-zA-Z0-9\-]+$/) ? 'invalid-format' : - username.length < 3 ? 'min-range' : - username.length > 20 ? 'max-range' : - null; - - if (err) { - this.update({ - usernameState: err - }); - return; - } - - this.update({ - usernameState: 'wait' - }); - - this.api('username/available', { - username: username - }).then(result => { - this.update({ - usernameState: result.available ? 'ok' : 'unavailable' - }); - }).catch(err => { - this.update({ - usernameState: 'error' - }); - }); - }; - - this.onChangePassword = () => { - const password = this.$refs.password.value; - - if (password == '') { - this.passwordStrength = ''; - return; - } - - const strength = getPasswordStrength(password); - this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low'; - this.update(); - this.$refs.passwordMetar.style.width = `${strength * 100}%`; - }; - - this.onChangePasswordRetype = () => { - const password = this.$refs.password.value; - const retypedPassword = this.$refs.passwordRetype.value; - - if (retypedPassword == '') { - this.passwordRetypeState = null; - return; - } - - this.passwordRetypeState = password == retypedPassword ? 'match' : 'not-match'; - }; - - this.onsubmit = e => { - e.preventDefault(); - - const username = this.$refs.username.value; - const password = this.$refs.password.value; - - const locker = document.body.appendChild(document.createElement('mk-locker')); - - this.api('signup', { - username: username, - password: password, - 'g-recaptcha-response': grecaptcha.getResponse() - }).then(() => { - this.api('signin', { - username: username, - password: password - }).then(() => { - location.href = '/'; - }); - }).catch(() => { - alert('%i18n:common.tags.mk-signup.some-error%'); - - grecaptcha.reset(); - this.recaptchaed = false; - - locker.parentNode.removeChild(locker); - }); - - return false; - }; - </script> -</mk-signup> diff --git a/src/web/app/common/views/components/index.ts b/src/web/app/common/views/components/index.ts new file mode 100644 index 0000000000..b1c5df8197 --- /dev/null +++ b/src/web/app/common/views/components/index.ts @@ -0,0 +1,7 @@ +import Vue from 'vue'; + +import signin from './signin.vue'; +import signup from './signup.vue'; + +Vue.component('mk-signin', signin); +Vue.component('mk-signup', signup); diff --git a/src/web/app/common/tags/poll.vue b/src/web/app/common/views/components/poll.vue index d85caa00ce..d85caa00ce 100644 --- a/src/web/app/common/tags/poll.vue +++ b/src/web/app/common/views/components/poll.vue diff --git a/src/web/app/common/tags/reaction-icon.vue b/src/web/app/common/views/components/reaction-icon.vue index 317daf0feb..317daf0feb 100644 --- a/src/web/app/common/tags/reaction-icon.vue +++ b/src/web/app/common/views/components/reaction-icon.vue diff --git a/src/web/app/common/tags/reaction-picker.vue b/src/web/app/common/views/components/reaction-picker.vue index dd4d1380b7..dd4d1380b7 100644 --- a/src/web/app/common/tags/reaction-picker.vue +++ b/src/web/app/common/views/components/reaction-picker.vue diff --git a/src/web/app/common/tags/reactions-viewer.vue b/src/web/app/common/views/components/reactions-viewer.vue index f6e37caa44..f6e37caa44 100644 --- a/src/web/app/common/tags/reactions-viewer.vue +++ b/src/web/app/common/views/components/reactions-viewer.vue diff --git a/src/web/app/common/views/components/signin.vue b/src/web/app/common/views/components/signin.vue new file mode 100644 index 0000000000..5ffc518b3c --- /dev/null +++ b/src/web/app/common/views/components/signin.vue @@ -0,0 +1,138 @@ +<template> +<form class="form" :class="{ signing: signing }" @submit.prevent="onSubmit"> + <label class="user-name"> + <input v-model="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="%i18n:common.tags.mk-signin.username%" autofocus required @change="onUsernameChange"/>%fa:at% + </label> + <label class="password"> + <input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signin.password%" required/>%fa:lock% + </label> + <label class="token" v-if="user && user.two_factor_enabled"> + <input v-model="token" type="number" placeholder="%i18n:common.tags.mk-signin.token%" required/>%fa:lock% + </label> + <button type="submit" disabled={ signing }>{ signing ? '%i18n:common.tags.mk-signin.signing-in%' : '%i18n:common.tags.mk-signin.signin%' }</button> +</form> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + props: ['os'], + data() { + return { + signing: false, + user: null + }; + }, + methods: { + onUsernameChange() { + this.os.api('users/show', { + username: this.username + }).then(user => { + this.user = user; + }); + }, + onSubmit() { + this.signing = true; + + this.os.api('signin', { + username: this.username, + password: this.password, + token: this.user && this.user.two_factor_enabled ? this.token : undefined + }).then(() => { + location.reload(); + }).catch(() => { + alert('something happened'); + this.signing = false; + }); + } + } +}); +</script> + +<style lang="stylus" scoped> +.form + display block + z-index 2 + + &.signing + &, * + cursor wait !important + + label + display block + margin 12px 0 + + [data-fa] + display block + pointer-events none + position absolute + bottom 0 + top 0 + left 0 + z-index 1 + margin auto + padding 0 16px + height 1em + color #898786 + + input[type=text] + input[type=password] + input[type=number] + user-select text + display inline-block + cursor auto + padding 0 0 0 38px + margin 0 + width 100% + line-height 44px + font-size 1em + color rgba(0, 0, 0, 0.7) + background #fff + outline none + border solid 1px #eee + border-radius 4px + + &:hover + background rgba(255, 255, 255, 0.7) + border-color #ddd + + & + i + color #797776 + + &:focus + background #fff + border-color #ccc + + & + i + color #797776 + + [type=submit] + cursor pointer + padding 16px + margin -6px 0 0 0 + width 100% + font-size 1.2em + color rgba(0, 0, 0, 0.5) + outline none + border none + border-radius 0 + background transparent + transition all .5s ease + + &:hover + color $theme-color + transition all .2s ease + + &:focus + color $theme-color + transition all .2s ease + + &:active + color darken($theme-color, 30%) + transition all .2s ease + + &:disabled + opacity 0.7 + +</style> diff --git a/src/web/app/common/views/components/signup.vue b/src/web/app/common/views/components/signup.vue new file mode 100644 index 0000000000..1734f77316 --- /dev/null +++ b/src/web/app/common/views/components/signup.vue @@ -0,0 +1,331 @@ +<template> +<form @submit.prevent="onSubmit" autocomplete="off"> + <label class="username"> + <p class="caption">%fa:at%%i18n:common.tags.mk-signup.username%</p> + <input v-model="username" type="text" pattern="^[a-zA-Z0-9-]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @keyup="onChangeUsername"/> + <p class="profile-page-url-preview" v-if="refs.username.value != '' && username-state != 'invalidFormat' && username-state != 'minRange' && username-state != 'maxRange'">{ _URL_ + '/' + refs.username.value }</p> + <p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:common.tags.mk-signup.checking%</p> + <p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.available%</p> + <p class="info" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.unavailable%</p> + <p class="info" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.error%</p> + <p class="info" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.invalid-format%</p> + <p class="info" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.too-short%</p> + <p class="info" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.too-long%</p> + </label> + <label class="password"> + <p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%</p> + <input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signup.password-placeholder%" autocomplete="off" required @keyup="onChangePassword"/> + <div class="meter" v-if="passwordStrength != ''" :data-strength="passwordStrength"> + <div class="value" ref="passwordMetar"></div> + </div> + <p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.weak-password%</p> + <p class="info" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.normal-password%</p> + <p class="info" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.strong-password%</p> + </label> + <label class="retype-password"> + <p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%(%i18n:common.tags.mk-signup.retype%)</p> + <input v-model="passwordRetype" type="password" placeholder="%i18n:common.tags.mk-signup.retype-placeholder%" autocomplete="off" required @keyup="onChangePasswordRetype"/> + <p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.password-matched%</p> + <p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.password-not-matched%</p> + </label> + <label class="recaptcha"> + <p class="caption"><template v-if="recaptchaed">%fa:toggle-on%</template><template v-if="!recaptchaed">%fa:toggle-off%</template>%i18n:common.tags.mk-signup.recaptcha%</p> + <div v-if="recaptcha" class="g-recaptcha" data-callback="onRecaptchaed" data-expired-callback="onRecaptchaExpired" data-sitekey="recaptcha.site_key"></div> + </label> + <label class="agree-tou"> + <input name="agree-tou" type="checkbox" autocomplete="off" required/> + <p><a :href="touUrl" target="_blank">利用規約</a>に同意する</p> + </label> + <button type="submit">%i18n:common.tags.mk-signup.create%</button> +</form> +</template> + +<script lang="ts"> +import Vue from 'vue'; +const getPasswordStrength = require('syuilo-password-strength'); +import + +const aboutUrl = `${_DOCS_URL_}/${_LANG_}/tou`; + +export default Vue.extend({ + methods: { + onSubmit() { + + } + }, + mounted() { + const head = document.getElementsByTagName('head')[0]; + const script = document.createElement('script'); + script.setAttribute('src', 'https://www.google.com/recaptcha/api.js'); + head.appendChild(script); + } +}); +</script> + +<style lang="stylus" scoped> + :scope + display block + min-width 302px + overflow hidden + + > form + + label + display block + margin 16px 0 + + > .caption + margin 0 0 4px 0 + color #828888 + font-size 0.95em + + > [data-fa] + margin-right 0.25em + color #96adac + + > .info + display block + margin 4px 0 + font-size 0.8em + + > [data-fa] + margin-right 0.3em + + &.username + .profile-page-url-preview + display block + margin 4px 8px 0 4px + font-size 0.8em + color #888 + + &:empty + display none + + &:not(:empty) + .info + margin-top 0 + + &.password + .meter + display block + margin-top 8px + width 100% + height 8px + + &[data-strength=''] + display none + + &[data-strength='low'] + > .value + background #d73612 + + &[data-strength='medium'] + > .value + background #d7ca12 + + &[data-strength='high'] + > .value + background #61bb22 + + > .value + display block + width 0% + height 100% + background transparent + border-radius 4px + transition all 0.1s ease + + [type=text], [type=password] + user-select text + display inline-block + cursor auto + padding 0 12px + margin 0 + width 100% + line-height 44px + font-size 1em + color #333 !important + background #fff !important + outline none + border solid 1px rgba(0, 0, 0, 0.1) + border-radius 4px + box-shadow 0 0 0 114514px #fff inset + transition all .3s ease + + &:hover + border-color rgba(0, 0, 0, 0.2) + transition all .1s ease + + &:focus + color $theme-color !important + border-color $theme-color + box-shadow 0 0 0 1024px #fff inset, 0 0 0 4px rgba($theme-color, 10%) + transition all 0s ease + + &:disabled + opacity 0.5 + + .agree-tou + padding 4px + border-radius 4px + + &:hover + background #f4f4f4 + + &:active + background #eee + + &, * + cursor pointer + + p + display inline + color #555 + + button + margin 0 0 32px 0 + padding 16px + width 100% + font-size 1em + color #fff + background $theme-color + border-radius 3px + + &:hover + background lighten($theme-color, 5%) + + &:active + background darken($theme-color, 5%) + +</style> + +<script lang="typescript"> + this.mixin('api'); + + + this.usernameState = null; + this.passwordStrength = ''; + this.passwordRetypeState = null; + this.recaptchaed = false; + + this.aboutUrl = `${_DOCS_URL_}/${_LANG_}/tou`; + + window.onRecaptchaed = () => { + this.recaptchaed = true; + this.update(); + }; + + window.onRecaptchaExpired = () => { + this.recaptchaed = false; + this.update(); + }; + + this.on('mount', () => { + this.update({ + recaptcha: { + site_key: _RECAPTCHA_SITEKEY_ + } + }); + + const head = document.getElementsByTagName('head')[0]; + const script = document.createElement('script'); + script.setAttribute('src', 'https://www.google.com/recaptcha/api.js'); + head.appendChild(script); + }); + + this.onChangeUsername = () => { + const username = this.$refs.username.value; + + if (username == '') { + this.update({ + usernameState: null + }); + return; + } + + const err = + !username.match(/^[a-zA-Z0-9\-]+$/) ? 'invalid-format' : + username.length < 3 ? 'min-range' : + username.length > 20 ? 'max-range' : + null; + + if (err) { + this.update({ + usernameState: err + }); + return; + } + + this.update({ + usernameState: 'wait' + }); + + this.api('username/available', { + username: username + }).then(result => { + this.update({ + usernameState: result.available ? 'ok' : 'unavailable' + }); + }).catch(err => { + this.update({ + usernameState: 'error' + }); + }); + }; + + this.onChangePassword = () => { + const password = this.$refs.password.value; + + if (password == '') { + this.passwordStrength = ''; + return; + } + + const strength = getPasswordStrength(password); + this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low'; + this.update(); + this.$refs.passwordMetar.style.width = `${strength * 100}%`; + }; + + this.onChangePasswordRetype = () => { + const password = this.$refs.password.value; + const retypedPassword = this.$refs.passwordRetype.value; + + if (retypedPassword == '') { + this.passwordRetypeState = null; + return; + } + + this.passwordRetypeState = password == retypedPassword ? 'match' : 'not-match'; + }; + + this.onsubmit = e => { + e.preventDefault(); + + const username = this.$refs.username.value; + const password = this.$refs.password.value; + + const locker = document.body.appendChild(document.createElement('mk-locker')); + + this.api('signup', { + username: username, + password: password, + 'g-recaptcha-response': grecaptcha.getResponse() + }).then(() => { + this.api('signin', { + username: username, + password: password + }).then(() => { + location.href = '/'; + }); + }).catch(() => { + alert('%i18n:common.tags.mk-signup.some-error%'); + + grecaptcha.reset(); + this.recaptchaed = false; + + locker.parentNode.removeChild(locker); + }); + + return false; + }; +</script> diff --git a/src/web/app/common/tags/stream-indicator.vue b/src/web/app/common/views/components/stream-indicator.vue index 0721c77ad7..0721c77ad7 100644 --- a/src/web/app/common/tags/stream-indicator.vue +++ b/src/web/app/common/views/components/stream-indicator.vue diff --git a/src/web/app/common/tags/time.vue b/src/web/app/common/views/components/time.vue index 7d165fc006..7d165fc006 100644 --- a/src/web/app/common/tags/time.vue +++ b/src/web/app/common/views/components/time.vue diff --git a/src/web/app/common/tags/url-preview.vue b/src/web/app/common/views/components/url-preview.vue index 88158db845..88158db845 100644 --- a/src/web/app/common/tags/url-preview.vue +++ b/src/web/app/common/views/components/url-preview.vue diff --git a/src/web/app/common/tags/url.vue b/src/web/app/common/views/components/url.vue index 4cc76f7e24..4cc76f7e24 100644 --- a/src/web/app/common/tags/url.vue +++ b/src/web/app/common/views/components/url.vue diff --git a/src/web/app/desktop/views/pages/welcome.vue b/src/web/app/desktop/views/pages/welcome.vue index c0e1c0bd4f..68b5f4cc98 100644 --- a/src/web/app/desktop/views/pages/welcome.vue +++ b/src/web/app/desktop/views/pages/welcome.vue @@ -17,105 +17,113 @@ <p class="c">{ _COPYRIGHT_ }</p> </div> </footer> + <modal name="signup"> + <mk-signup/> + </modal> </div> </template> -<style> - #wait { - right: auto; - left: 15px; +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + methods: { + signup() { + this.$modal.show('signup'); + } } +}); +</script> + +<style> +#wait { + right: auto; + left: 15px; +} </style> <style lang="stylus" scoped> - .root +.root + display flex + flex-direction column + flex 1 + background #eee + $width = 1000px + + > main display flex - flex-direction column flex 1 - background #eee - $width = 1000px - - > main - display flex - flex 1 - max-width $width - margin 0 auto - padding 80px 0 0 0 + max-width $width + margin 0 auto + padding 80px 0 0 0 - > div:first-child - margin 0 auto 0 0 - width calc(100% - 500px) - color #777 + > div:first-child + margin 0 auto 0 0 + width calc(100% - 500px) + color #777 - > h1 - margin 0 - font-weight normal - font-variant small-caps - letter-spacing 12px + > h1 + margin 0 + font-weight normal + font-variant small-caps + letter-spacing 12px - > p - margin 0.5em 0 - line-height 2em + > p + margin 0.5em 0 + line-height 2em - button - padding 8px 16px - font-size inherit + button + padding 8px 16px + font-size inherit - .signup - color $theme-color - border solid 2px $theme-color - border-radius 4px + .signup + color $theme-color + border solid 2px $theme-color + border-radius 4px - &:focus - box-shadow 0 0 0 3px rgba($theme-color, 0.2) + &:focus + box-shadow 0 0 0 3px rgba($theme-color, 0.2) - &:hover - color $theme-color-foreground - background $theme-color + &:hover + color $theme-color-foreground + background $theme-color - &:active - color $theme-color-foreground - background darken($theme-color, 10%) - border-color darken($theme-color, 10%) + &:active + color $theme-color-foreground + background darken($theme-color, 10%) + border-color darken($theme-color, 10%) - .signin - &:focus - color #444 + .signin + &:focus + color #444 - &:hover - color #444 + &:hover + color #444 - &:active - color #333 + &:active + color #333 - > div:last-child - margin 0 0 0 auto + > div:last-child + margin 0 0 0 auto - > footer - background #fff + > footer + background #fff - * - color #fff !important - text-shadow 0 0 8px #000 - font-weight bold + * + color #fff !important + text-shadow 0 0 8px #000 + font-weight bold - > div - max-width $width - margin 0 auto - padding 16px 0 - text-align center - border-top solid 1px #fff + > div + max-width $width + margin 0 auto + padding 16px 0 + text-align center + border-top solid 1px #fff - > .c - margin 0 - line-height 64px - font-size 10px + > .c + margin 0 + line-height 64px + font-size 10px </style> - -<script lang="ts"> -import Vue from 'vue' -export default Vue.extend({ - -}) -</script> diff --git a/src/web/app/init.ts b/src/web/app/init.ts index 796a966940..20ea1df8b2 100644 --- a/src/web/app/init.ts +++ b/src/web/app/init.ts @@ -9,8 +9,10 @@ declare const _HOST_: string; import Vue from 'vue'; import VueRouter from 'vue-router'; +import VModal from 'vue-js-modal'; Vue.use(VueRouter); +Vue.use(VModal); import App from './app.vue'; |