mirror of https://github.com/jumpserver/jumpserver
perf: 增加国际电话区号选择
parent
973df0360c
commit
f606dd8920
|
@ -19,3 +19,17 @@ class Status(models.TextChoices):
|
||||||
failed = 'failed', _("Failed")
|
failed = 'failed', _("Failed")
|
||||||
error = 'error', _("Error")
|
error = 'error', _("Error")
|
||||||
canceled = 'canceled', _("Canceled")
|
canceled = 'canceled', _("Canceled")
|
||||||
|
|
||||||
|
|
||||||
|
COUNTRY_CALLING_CODES = [
|
||||||
|
{'name': 'China(中国)', 'value': '+86'},
|
||||||
|
{'name': 'HongKong(中国香港)', 'value': '+852'},
|
||||||
|
{'name': 'Macao(中国澳门)', 'value': '+853'},
|
||||||
|
{'name': 'Taiwan(中国台湾)', 'value': '+886'},
|
||||||
|
{'name': 'America(America)', 'value': '+1'}, {'name': 'Russia(Россия)', 'value': '+7'},
|
||||||
|
{'name': 'France(français)', 'value': '+33'},
|
||||||
|
{'name': 'Britain(Britain)', 'value': '+44'},
|
||||||
|
{'name': 'Germany(Deutschland)', 'value': '+49'},
|
||||||
|
{'name': 'Japan(日本)', 'value': '+81'}, {'name': 'Korea(한국)', 'value': '+82'},
|
||||||
|
{'name': 'India(भारत)', 'value': '+91'}
|
||||||
|
]
|
||||||
|
|
|
@ -3,6 +3,7 @@ from rest_framework import generics
|
||||||
from rest_framework.permissions import AllowAny
|
from rest_framework.permissions import AllowAny
|
||||||
|
|
||||||
from authentication.permissions import IsValidUserOrConnectionToken
|
from authentication.permissions import IsValidUserOrConnectionToken
|
||||||
|
from common.const.choices import COUNTRY_CALLING_CODES
|
||||||
from common.utils import get_logger, lazyproperty
|
from common.utils import get_logger, lazyproperty
|
||||||
from common.utils.timezone import local_now
|
from common.utils.timezone import local_now
|
||||||
from .. import serializers
|
from .. import serializers
|
||||||
|
@ -24,7 +25,8 @@ class OpenPublicSettingApi(generics.RetrieveAPIView):
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return {
|
return {
|
||||||
"XPACK_ENABLED": settings.XPACK_ENABLED,
|
"XPACK_ENABLED": settings.XPACK_ENABLED,
|
||||||
"INTERFACE": self.interface_setting
|
"INTERFACE": self.interface_setting,
|
||||||
|
"COUNTRY_CALLING_CODES": COUNTRY_CALLING_CODES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ __all__ = [
|
||||||
class PublicSettingSerializer(serializers.Serializer):
|
class PublicSettingSerializer(serializers.Serializer):
|
||||||
XPACK_ENABLED = serializers.BooleanField()
|
XPACK_ENABLED = serializers.BooleanField()
|
||||||
INTERFACE = serializers.DictField()
|
INTERFACE = serializers.DictField()
|
||||||
|
COUNTRY_CALLING_CODES = serializers.ListField()
|
||||||
|
|
||||||
|
|
||||||
class PrivateSettingSerializer(PublicSettingSerializer):
|
class PrivateSettingSerializer(PublicSettingSerializer):
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
.margin-bottom {
|
.margin-bottom {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-style {
|
.input-style {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -22,6 +23,19 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scrollable-menu {
|
||||||
|
height: auto;
|
||||||
|
max-height: 18rem;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
.input-group-btn .btn-secondary {
|
||||||
|
color: #464a4c;
|
||||||
|
background-color: #eceeef;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block html_title %}{% trans 'Forgot password' %}{% endblock %}
|
{% block html_title %}{% trans 'Forgot password' %}{% endblock %}
|
||||||
|
@ -57,9 +71,26 @@
|
||||||
placeholder="{% trans 'Email account' %}" value="{{ email }}">
|
placeholder="{% trans 'Email account' %}" value="{{ email }}">
|
||||||
</div>
|
</div>
|
||||||
<div id="validate-sms" class="validate-field margin-bottom">
|
<div id="validate-sms" class="validate-field margin-bottom">
|
||||||
<input type="tel" id="sms" name="sms" class="form-control input-style"
|
<div class="input-group">
|
||||||
placeholder="{% trans 'Mobile number' %}" value="{{ sms }}">
|
<div class="input-group-btn">
|
||||||
<small style="color: #999; margin-left: 5px">{{ form.sms.help_text }}</small>
|
<button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown"
|
||||||
|
aria-haspopup="true" aria-expanded="false">
|
||||||
|
<span class="country-code-value">+86</span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu scrollable-menu">
|
||||||
|
{% for country in countries %}
|
||||||
|
<li>
|
||||||
|
<a href="#" class="dropdown-item d-flex justify-content-between">
|
||||||
|
<span class="country-name text-left">{{ country.name }}</span>
|
||||||
|
<span class="country-code">{{ country.value }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<input type="tel" id="sms" name="sms" class="form-control input-style"
|
||||||
|
placeholder="{% trans 'Mobile number' %}" value="{{ sms }}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="margin-bottom challenge-required">
|
<div class="margin-bottom challenge-required">
|
||||||
<input type="text" id="code" name="code" class="form-control input-style"
|
<input type="text" id="code" name="code" class="form-control input-style"
|
||||||
|
@ -76,7 +107,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$(function (){
|
$(function () {
|
||||||
const validateSelectRef = $('#validate-backend-select')
|
const validateSelectRef = $('#validate-backend-select')
|
||||||
const formType = $('input[name="form_type"]').val()
|
const formType = $('input[name="form_type"]').val()
|
||||||
validateSelectRef.val(formType)
|
validateSelectRef.val(formType)
|
||||||
|
@ -84,19 +115,31 @@
|
||||||
selectChange(formType);
|
selectChange(formType);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$(".dropdown-menu li a").click(function (evt) {
|
||||||
|
const inputGroup = $('.input-group');
|
||||||
|
const inputGroupAddon = inputGroup.find('.country-code-value');
|
||||||
|
const selectedCountry = $(evt.target).closest('li');
|
||||||
|
const selectedCountryCode = selectedCountry.find('.country-code').html();
|
||||||
|
inputGroupAddon.html(selectedCountryCode)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
function getQueryString(name) {
|
function getQueryString(name) {
|
||||||
const reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
|
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
|
||||||
const r = window.location.search.substr(1).match(reg);
|
const r = window.location.search.substr(1).match(reg);
|
||||||
if(r !== null)
|
if (r !== null)
|
||||||
return unescape(r[2])
|
return unescape(r[2])
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectChange(name) {
|
function selectChange(name) {
|
||||||
$('.validate-field').hide()
|
$('.validate-field').hide()
|
||||||
$('#validate-' + name).show()
|
$('#validate-' + name).show()
|
||||||
$('#validate-' + name + '-tip').show()
|
$('#validate-' + name + '-tip').show()
|
||||||
$('input[name="form_type"]').attr('value', name)
|
$('input[name="form_type"]').attr('value', name)
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendChallengeCode(currentBtn) {
|
function sendChallengeCode(currentBtn) {
|
||||||
let time = 60;
|
let time = 60;
|
||||||
const token = getQueryString('token')
|
const token = getQueryString('token')
|
||||||
|
@ -104,7 +147,7 @@
|
||||||
|
|
||||||
const formType = $('input[name="form_type"]').val()
|
const formType = $('input[name="form_type"]').val()
|
||||||
const email = $('#email').val()
|
const email = $('#email').val()
|
||||||
const sms = $('#sms').val()
|
let sms = $('#sms').val();
|
||||||
const errMsg = "{% trans 'The {} cannot be empty' %}"
|
const errMsg = "{% trans 'The {} cannot be empty' %}"
|
||||||
|
|
||||||
if (formType === 'sms') {
|
if (formType === 'sms') {
|
||||||
|
@ -118,10 +161,11 @@
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sms = $(".input-group .country-code-value").html() + sms
|
||||||
const data = {
|
const data = {
|
||||||
form_type: formType, email: email, sms: sms,
|
form_type: formType, email: email, sms: sms,
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSuccess() {
|
function onSuccess() {
|
||||||
const originBtnText = currentBtn.innerHTML;
|
const originBtnText = currentBtn.innerHTML;
|
||||||
currentBtn.disabled = true
|
currentBtn.disabled = true
|
||||||
|
|
|
@ -13,6 +13,7 @@ from django.views.generic import FormView, RedirectView
|
||||||
|
|
||||||
from authentication.errors import IntervalTooShort
|
from authentication.errors import IntervalTooShort
|
||||||
from authentication.utils import check_user_property_is_correct
|
from authentication.utils import check_user_property_is_correct
|
||||||
|
from common.const.choices import COUNTRY_CALLING_CODES
|
||||||
from common.utils import FlashMessageUtil, get_object_or_none, random_string
|
from common.utils import FlashMessageUtil, get_object_or_none, random_string
|
||||||
from common.utils.verify_code import SendAndVerifyCodeUtil
|
from common.utils.verify_code import SendAndVerifyCodeUtil
|
||||||
from users.notifications import ResetPasswordSuccessMsg
|
from users.notifications import ResetPasswordSuccessMsg
|
||||||
|
@ -108,7 +109,7 @@ class UserForgotPasswordView(FormView):
|
||||||
for k, v in cleaned_data.items():
|
for k, v in cleaned_data.items():
|
||||||
if v:
|
if v:
|
||||||
context[k] = v
|
context[k] = v
|
||||||
|
context['countries'] = COUNTRY_CALLING_CODES
|
||||||
context['form_type'] = 'email'
|
context['form_type'] = 'email'
|
||||||
context['XPACK_ENABLED'] = settings.XPACK_ENABLED
|
context['XPACK_ENABLED'] = settings.XPACK_ENABLED
|
||||||
validate_backends = self.get_validate_backends_context(has_phone)
|
validate_backends = self.get_validate_backends_context(has_phone)
|
||||||
|
|
Loading…
Reference in New Issue