RecoveryCodeEntryView.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Puter.
  5. *
  6. * Puter is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. const Component = use('util.Component');
  20. export default def(class RecoveryCodeEntryView extends Component {
  21. static ID = 'ui.component.RecoveryCodeEntryView';
  22. static PROPERTIES = {
  23. value: {},
  24. length: { value: 8 },
  25. error: {},
  26. }
  27. static CSS = /*css*/`
  28. fieldset {
  29. display: flex;
  30. }
  31. .recovery-code-input {
  32. flex-grow: 1;
  33. box-sizing: border-box;
  34. height: 50px;
  35. font-size: 25px;
  36. text-align: center;
  37. border-radius: 0.5rem;
  38. font-family: 'Courier New', Courier, monospace;
  39. }
  40. /* TODO: I'd rather not duplicate this */
  41. .error {
  42. display: none;
  43. color: red;
  44. border: 1px solid red;
  45. border-radius: 4px;
  46. padding: 9px;
  47. margin-bottom: 15px;
  48. text-align: center;
  49. font-size: 13px;
  50. }
  51. .error-message {
  52. display: none;
  53. color: rgb(215 2 2);
  54. font-size: 14px;
  55. margin-top: 10px;
  56. margin-bottom: 10px;
  57. padding: 10px;
  58. border-radius: 4px;
  59. border: 1px solid rgb(215 2 2);
  60. text-align: center;
  61. }
  62. `;
  63. create_template ({ template }) {
  64. $(template).html(/*html*/`
  65. <div class="recovery-code-entry">
  66. <form>
  67. <div class="error"></div>
  68. <fieldset name="recovery-code" style="border: none; padding:0;" data-recovery-code-form>
  69. <input type="text" class="recovery-code-input" placeholder="${i18n('login2fa_recovery_placeholder')}" maxlength="${this.get('length')}" required>
  70. </fieldset>
  71. </form>
  72. </div>
  73. `);
  74. }
  75. on_focus () {
  76. $(this.dom_).find('input').focus();
  77. }
  78. on_ready ({ listen }) {
  79. listen('error', (error) => {
  80. if ( ! error ) return $(this.dom_).find('.error').hide();
  81. $(this.dom_).find('.error').text(error).show();
  82. });
  83. listen('value', (value) => {
  84. // clear input
  85. if ( value === undefined ) {
  86. $(this.dom_).find('input').val('');
  87. }
  88. });
  89. const input = $(this.dom_).find('input');
  90. input.on('input', () => {
  91. if ( input.val().length === this.get('length') ) {
  92. this.set('value', input.val());
  93. }
  94. });
  95. }
  96. });