Login.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <template>
  2. <div>
  3. <metadata title="Login" v-if="isPage" />
  4. <div class="modal is-active">
  5. <div class="modal-background" @click="closeLoginModal()" />
  6. <div class="modal-card">
  7. <header class="modal-card-head">
  8. <p class="modal-card-title">Login</p>
  9. <button
  10. v-if="!isPage"
  11. class="delete"
  12. @click="closeLoginModal()"
  13. />
  14. </header>
  15. <section class="modal-card-body">
  16. <form>
  17. <!-- email address -->
  18. <p class="control">
  19. <label class="label">Email</label>
  20. <input
  21. v-model="email"
  22. class="input"
  23. type="email"
  24. placeholder="Email..."
  25. @keypress="submitOnEnter(submitModal, $event)"
  26. />
  27. </p>
  28. <!-- password -->
  29. <p class="control">
  30. <label class="label">Password</label>
  31. </p>
  32. <div id="password-visibility-container">
  33. <input
  34. v-model="password.value"
  35. class="input"
  36. type="password"
  37. ref="password"
  38. placeholder="Password..."
  39. @input="checkForAutofill($event)"
  40. @keypress="submitOnEnter(submitModal, $event)"
  41. />
  42. <a @click="togglePasswordVisibility()">
  43. <i class="material-icons">
  44. {{
  45. !password.visible
  46. ? "visibility"
  47. : "visibility_off"
  48. }}
  49. </i>
  50. </a>
  51. </div>
  52. <p class="content-box-optional-helper">
  53. <router-link
  54. id="forgot-password"
  55. href="#"
  56. to="/reset_password"
  57. @click.native="closeLoginModal()"
  58. >
  59. Forgot password?
  60. </router-link>
  61. </p>
  62. <br />
  63. <p>
  64. By logging in you agree to our
  65. <router-link
  66. to="/terms"
  67. @click.native="closeLoginModal()"
  68. >
  69. Terms of Service
  70. </router-link>
  71. &nbsp;and
  72. <router-link
  73. to="/privacy"
  74. @click.native="closeLoginModal()"
  75. >
  76. Privacy Policy </router-link
  77. >.
  78. </p>
  79. </form>
  80. </section>
  81. <footer class="modal-card-foot">
  82. <div id="actions">
  83. <a
  84. class="button is-primary"
  85. href="#"
  86. @click="submitModal()"
  87. >Login</a
  88. >
  89. <a
  90. class="button is-github"
  91. :href="apiDomain + '/auth/github/authorize'"
  92. @click="githubRedirect()"
  93. >
  94. <div class="icon">
  95. <img
  96. class="invert"
  97. src="/assets/social/github.svg"
  98. />
  99. </div>
  100. &nbsp;&nbsp;Login with GitHub
  101. </a>
  102. </div>
  103. <p class="content-box-optional-helper">
  104. <router-link to="/register" v-if="isPage">
  105. Don't have an account?
  106. </router-link>
  107. <a v-else href="#" @click="changeToRegisterModal()">
  108. Don't have an account?
  109. </a>
  110. </p>
  111. </footer>
  112. </div>
  113. </div>
  114. </div>
  115. </template>
  116. <script>
  117. import { mapActions } from "vuex";
  118. import Toast from "toasters";
  119. export default {
  120. data() {
  121. return {
  122. email: "",
  123. password: {
  124. value: "",
  125. visible: false
  126. },
  127. apiDomain: "",
  128. isPage: false
  129. };
  130. },
  131. async mounted() {
  132. this.apiDomain = await lofig.get("apiDomain");
  133. if (this.$route.path === "/login") this.isPage = true;
  134. },
  135. methods: {
  136. checkForAutofill(event) {
  137. if (
  138. event.target.value !== "" &&
  139. event.inputType === undefined &&
  140. event.data === undefined &&
  141. event.dataTransfer === undefined &&
  142. event.isComposing === undefined
  143. )
  144. this.submitModal();
  145. },
  146. submitOnEnter(cb, event) {
  147. if (event.which === 13) cb();
  148. },
  149. submitModal() {
  150. this.login({
  151. email: this.email,
  152. password: this.password.value
  153. })
  154. .then(res => {
  155. if (res.status === "success") window.location.reload();
  156. })
  157. .catch(err => new Toast(err.message));
  158. },
  159. togglePasswordVisibility() {
  160. if (this.$refs.password.type === "password") {
  161. this.$refs.password.type = "text";
  162. this.password.visible = true;
  163. } else {
  164. this.$refs.password.type = "password";
  165. this.password.visible = false;
  166. }
  167. },
  168. changeToRegisterModal() {
  169. if (!this.isPage) {
  170. this.closeLoginModal();
  171. this.openModal("register");
  172. }
  173. },
  174. closeLoginModal() {
  175. if (!this.isPage) this.closeModal("login");
  176. },
  177. githubRedirect() {
  178. if (!this.isPage)
  179. localStorage.setItem("github_redirect", this.$route.path);
  180. },
  181. ...mapActions("modalVisibility", ["closeModal", "openModal"]),
  182. ...mapActions("user/auth", ["login"])
  183. }
  184. };
  185. </script>
  186. <style lang="scss" scoped>
  187. .night-mode {
  188. .modal-card,
  189. .modal-card-head,
  190. .modal-card-body,
  191. .modal-card-foot {
  192. background-color: var(--dark-grey-3);
  193. }
  194. .label,
  195. p:not(.help) {
  196. color: var(--light-grey-2);
  197. }
  198. }
  199. .modal-card-foot {
  200. display: flex;
  201. justify-content: space-between;
  202. flex-wrap: wrap;
  203. .content-box-optional-helper {
  204. margin-top: 0;
  205. }
  206. }
  207. .button.is-github {
  208. background-color: var(--dark-grey-2);
  209. color: var(--white) !important;
  210. }
  211. .is-github:focus {
  212. background-color: var(--dark-grey-4);
  213. }
  214. .is-primary:focus {
  215. background-color: var(--primary-color) !important;
  216. }
  217. .invert {
  218. filter: brightness(5);
  219. }
  220. </style>