forked from github/plane
[WEB-1319] chore: handled redirection when user is not logged in (#4497)
* chore: handled redirection when user is not logged in * dev: handle url redirection in space app * dev: remove user from redis on successful code matching
This commit is contained in:
parent
c2e293cf3b
commit
2988d5e429
@ -125,6 +125,8 @@ class MagicCodeProvider(CredentialAdapter):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
# Delete the token from redis if the code match is successful
|
||||||
|
ri.delete(self.key)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise AuthenticationException(
|
raise AuthenticationException(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
from urllib.parse import urlencode, urljoin
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
# Django imports
|
# Django imports
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
@ -36,10 +36,7 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# set the referer as session to redirect after login
|
# set the referer as session to redirect after login
|
||||||
@ -58,10 +55,7 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Validate email
|
# Validate email
|
||||||
@ -77,10 +71,7 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Existing User
|
# Existing User
|
||||||
@ -95,10 +86,7 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
if not existing_user.is_active:
|
if not existing_user.is_active:
|
||||||
@ -111,10 +99,7 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -125,19 +110,13 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to next path
|
# redirect to next path
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
str(next_path) if next_path else "",
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -158,10 +137,7 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
email = request.POST.get("email", False)
|
email = request.POST.get("email", False)
|
||||||
@ -179,10 +155,7 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
# Validate the email
|
# Validate the email
|
||||||
email = email.strip().lower()
|
email = email.strip().lower()
|
||||||
@ -198,10 +171,7 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Existing User
|
# Existing User
|
||||||
@ -218,10 +188,7 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
exc = AuthenticationException(
|
exc = AuthenticationException(
|
||||||
@ -232,10 +199,7 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -246,17 +210,11 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
str(next_path) if next_path else "",
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode, urljoin
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -38,10 +38,7 @@ class GitHubOauthInitiateSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -54,10 +51,7 @@ class GitHubOauthInitiateSpaceEndpoint(View):
|
|||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -79,10 +73,7 @@ class GitHubCallbackSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host,
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
@ -95,10 +86,7 @@ class GitHubCallbackSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host,
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -111,14 +99,11 @@ class GitHubCallbackSpaceEndpoint(View):
|
|||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# Process workspace and project invitations
|
# Process workspace and project invitations
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = urljoin(base_host, str(next_path) if next_path else "")
|
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host,
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode, urljoin
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -36,10 +36,7 @@ class GoogleOauthInitiateSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -52,10 +49,7 @@ class GoogleOauthInitiateSpaceEndpoint(View):
|
|||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -76,10 +70,7 @@ class GoogleCallbackSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host,
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
if not code:
|
if not code:
|
||||||
exc = AuthenticationException(
|
exc = AuthenticationException(
|
||||||
@ -91,10 +82,7 @@ class GoogleCallbackSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = next_path
|
params["next_path"] = next_path
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host,
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
try:
|
try:
|
||||||
provider = GoogleOAuthProvider(
|
provider = GoogleOAuthProvider(
|
||||||
@ -105,16 +93,11 @@ class GoogleCallbackSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
||||||
base_host, str(next_path) if next_path else "/spaces"
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host,
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
from urllib.parse import urlencode, urljoin
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
# Django imports
|
# Django imports
|
||||||
from django.core.validators import validate_email
|
from django.core.validators import validate_email
|
||||||
@ -84,10 +84,7 @@ class MagicSignInSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
existing_user = User.objects.filter(email=email).first()
|
existing_user = User.objects.filter(email=email).first()
|
||||||
@ -100,10 +97,7 @@ class MagicSignInSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Active User
|
# Active User
|
||||||
@ -117,10 +111,7 @@ class MagicSignInSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
try:
|
try:
|
||||||
provider = MagicCodeProvider(
|
provider = MagicCodeProvider(
|
||||||
@ -136,17 +127,14 @@ class MagicSignInSpaceEndpoint(View):
|
|||||||
else:
|
else:
|
||||||
# Get the redirection path
|
# Get the redirection path
|
||||||
path = str(next_path) if next_path else ""
|
path = str(next_path) if next_path else ""
|
||||||
url = urljoin(base_host(request=request, is_space=True), path)
|
url = f"{base_host(request=request, is_space=True)}{path}"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -169,10 +157,7 @@ class MagicSignUpSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
# Existing User
|
# Existing User
|
||||||
existing_user = User.objects.filter(email=email).first()
|
existing_user = User.objects.filter(email=email).first()
|
||||||
@ -185,10 +170,7 @@ class MagicSignUpSpaceEndpoint(View):
|
|||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -199,18 +181,12 @@ class MagicSignUpSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
str(next_path) if next_path else "spaces",
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(next_path)
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import os
|
import os
|
||||||
from urllib.parse import urlencode, urljoin
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
# Third party imports
|
# Third party imports
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
@ -145,10 +145,7 @@ class ResetPasswordSpaceEndpoint(View):
|
|||||||
error_message="INVALID_PASSWORD_TOKEN",
|
error_message="INVALID_PASSWORD_TOKEN",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}/accounts/reset-password/?{urlencode(params)}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"accounts/reset-password?" + urlencode(params),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
password = request.POST.get("password", False)
|
password = request.POST.get("password", False)
|
||||||
@ -158,10 +155,7 @@ class ResetPasswordSpaceEndpoint(View):
|
|||||||
error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD"],
|
error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD"],
|
||||||
error_message="INVALID_PASSWORD",
|
error_message="INVALID_PASSWORD",
|
||||||
)
|
)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}/accounts/reset-password/?{urlencode(exc.get_error_dict())}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"?" + urlencode(exc.get_error_dict()),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Check the password complexity
|
# Check the password complexity
|
||||||
@ -171,11 +165,7 @@ class ResetPasswordSpaceEndpoint(View):
|
|||||||
error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD"],
|
error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD"],
|
||||||
error_message="INVALID_PASSWORD",
|
error_message="INVALID_PASSWORD",
|
||||||
)
|
)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}/accounts/reset-password/?{urlencode(exc.get_error_dict())}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"accounts/reset-password?"
|
|
||||||
+ urlencode(exc.get_error_dict()),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# set_password also hashes the password that the user will get
|
# set_password also hashes the password that the user will get
|
||||||
@ -193,8 +183,5 @@ class ResetPasswordSpaceEndpoint(View):
|
|||||||
],
|
],
|
||||||
error_message="EXPIRED_PASSWORD_TOKEN",
|
error_message="EXPIRED_PASSWORD_TOKEN",
|
||||||
)
|
)
|
||||||
url = urljoin(
|
url = f"{base_host(request=request, is_space=True)}/accounts/reset-password/?{urlencode(exc.get_error_dict())}"
|
||||||
base_host(request=request, is_space=True),
|
|
||||||
"accounts/reset-password?" + urlencode(exc.get_error_dict()),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
// components
|
// components
|
||||||
@ -9,17 +10,18 @@ import { AuthView } from "@/components/views";
|
|||||||
import { useUser } from "@/hooks/store";
|
import { useUser } from "@/hooks/store";
|
||||||
|
|
||||||
function HomePage() {
|
function HomePage() {
|
||||||
const { fetchCurrentUser, isAuthenticated, isLoading } = useUser();
|
const { data: currentUser, fetchCurrentUser, isAuthenticated, isLoading } = useUser();
|
||||||
|
|
||||||
useSWR("CURRENT_USER", () => fetchCurrentUser(), { errorRetryCount: 0 });
|
useSWR("CURRENT_USER", () => fetchCurrentUser(), {
|
||||||
|
errorRetryCount: 0,
|
||||||
|
revalidateIfStale: false,
|
||||||
|
revalidateOnFocus: false,
|
||||||
|
refreshWhenHidden: false,
|
||||||
|
});
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) return <LogoSpinner />;
|
||||||
return <LogoSpinner />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAuthenticated) {
|
if (currentUser && isAuthenticated) return <UserLoggedIn />;
|
||||||
return <UserLoggedIn />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <AuthView />;
|
return <AuthView />;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ export const AuthRoot: FC = observer(() => {
|
|||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const emailParam = searchParams.get("email") || undefined;
|
const emailParam = searchParams.get("email") || undefined;
|
||||||
const error_code = searchParams.get("error_code") || undefined;
|
const error_code = searchParams.get("error_code") || undefined;
|
||||||
|
const nextPath = searchParams.get("next_path") || undefined;
|
||||||
// states
|
// states
|
||||||
const [authMode, setAuthMode] = useState<EAuthModes>(EAuthModes.SIGN_UP);
|
const [authMode, setAuthMode] = useState<EAuthModes>(EAuthModes.SIGN_UP);
|
||||||
const [authStep, setAuthStep] = useState<EAuthSteps>(EAuthSteps.EMAIL);
|
const [authStep, setAuthStep] = useState<EAuthSteps>(EAuthSteps.EMAIL);
|
||||||
@ -141,6 +142,7 @@ export const AuthRoot: FC = observer(() => {
|
|||||||
<AuthUniqueCodeForm
|
<AuthUniqueCodeForm
|
||||||
mode={authMode}
|
mode={authMode}
|
||||||
email={email}
|
email={email}
|
||||||
|
nextPath={nextPath}
|
||||||
handleEmailClear={() => {
|
handleEmailClear={() => {
|
||||||
setEmail("");
|
setEmail("");
|
||||||
setAuthStep(EAuthSteps.EMAIL);
|
setAuthStep(EAuthSteps.EMAIL);
|
||||||
@ -154,6 +156,7 @@ export const AuthRoot: FC = observer(() => {
|
|||||||
isPasswordAutoset={isPasswordAutoset}
|
isPasswordAutoset={isPasswordAutoset}
|
||||||
isSMTPConfigured={isSMTPConfigured}
|
isSMTPConfigured={isSMTPConfigured}
|
||||||
email={email}
|
email={email}
|
||||||
|
nextPath={nextPath}
|
||||||
handleEmailClear={() => {
|
handleEmailClear={() => {
|
||||||
setEmail("");
|
setEmail("");
|
||||||
setAuthStep(EAuthSteps.EMAIL);
|
setAuthStep(EAuthSteps.EMAIL);
|
||||||
|
@ -19,6 +19,7 @@ type Props = {
|
|||||||
isPasswordAutoset: boolean;
|
isPasswordAutoset: boolean;
|
||||||
isSMTPConfigured: boolean;
|
isSMTPConfigured: boolean;
|
||||||
mode: EAuthModes;
|
mode: EAuthModes;
|
||||||
|
nextPath: string | undefined;
|
||||||
handleEmailClear: () => void;
|
handleEmailClear: () => void;
|
||||||
handleAuthStep: (step: EAuthSteps) => void;
|
handleAuthStep: (step: EAuthSteps) => void;
|
||||||
};
|
};
|
||||||
@ -37,7 +38,7 @@ const defaultValues: TPasswordFormValues = {
|
|||||||
const authService = new AuthService();
|
const authService = new AuthService();
|
||||||
|
|
||||||
export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
||||||
const { email, isSMTPConfigured, handleAuthStep, handleEmailClear, mode } = props;
|
const { email, nextPath, isSMTPConfigured, handleAuthStep, handleEmailClear, mode } = props;
|
||||||
// states
|
// states
|
||||||
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
||||||
const [passwordFormData, setPasswordFormData] = useState<TPasswordFormValues>({ ...defaultValues, email });
|
const [passwordFormData, setPasswordFormData] = useState<TPasswordFormValues>({ ...defaultValues, email });
|
||||||
@ -65,6 +66,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const passwordSupport = passwordFormData.password.length > 0 &&
|
const passwordSupport = passwordFormData.password.length > 0 &&
|
||||||
|
mode === EAuthModes.SIGN_UP &&
|
||||||
(getPasswordStrength(passwordFormData.password) < 3 || isPasswordInputFocused) && (
|
(getPasswordStrength(passwordFormData.password) < 3 || isPasswordInputFocused) && (
|
||||||
<PasswordStrengthMeter password={passwordFormData.password} />
|
<PasswordStrengthMeter password={passwordFormData.password} />
|
||||||
);
|
);
|
||||||
@ -92,6 +94,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
|||||||
>
|
>
|
||||||
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
||||||
<input type="hidden" value={passwordFormData.email} name="email" />
|
<input type="hidden" value={passwordFormData.email} name="email" />
|
||||||
|
<input type="hidden" value={nextPath} name="next_path" />
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<label className="text-sm font-medium text-onboarding-text-300" htmlFor="email">
|
<label className="text-sm font-medium text-onboarding-text-300" htmlFor="email">
|
||||||
Email
|
Email
|
||||||
|
@ -18,6 +18,7 @@ const authService = new AuthService();
|
|||||||
type TAuthUniqueCodeForm = {
|
type TAuthUniqueCodeForm = {
|
||||||
mode: EAuthModes;
|
mode: EAuthModes;
|
||||||
email: string;
|
email: string;
|
||||||
|
nextPath: string | undefined;
|
||||||
handleEmailClear: () => void;
|
handleEmailClear: () => void;
|
||||||
generateEmailUniqueCode: (email: string) => Promise<{ code: string } | undefined>;
|
generateEmailUniqueCode: (email: string) => Promise<{ code: string } | undefined>;
|
||||||
};
|
};
|
||||||
@ -33,7 +34,7 @@ const defaultValues: TUniqueCodeFormValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
|
export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
|
||||||
const { mode, email, handleEmailClear, generateEmailUniqueCode } = props;
|
const { mode, email, nextPath, handleEmailClear, generateEmailUniqueCode } = props;
|
||||||
// hooks
|
// hooks
|
||||||
// const { captureEvent } = useEventTracker();
|
// const { captureEvent } = useEventTracker();
|
||||||
// derived values
|
// derived values
|
||||||
@ -81,6 +82,7 @@ export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
|
|||||||
>
|
>
|
||||||
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
||||||
<input type="hidden" value={uniqueCodeFormData.email} name="email" />
|
<input type="hidden" value={uniqueCodeFormData.email} name="email" />
|
||||||
|
<input type="hidden" value={nextPath} name="next_path" />
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<label className="text-sm font-medium text-onboarding-text-300" htmlFor="email">
|
<label className="text-sm font-medium text-onboarding-text-300" htmlFor="email">
|
||||||
Email
|
Email
|
||||||
|
@ -18,10 +18,10 @@ export const OAuthOptions: React.FC = observer(() => {
|
|||||||
<div className={`mt-7 grid gap-4 overflow-hidden`}>
|
<div className={`mt-7 grid gap-4 overflow-hidden`}>
|
||||||
{instance?.config?.is_google_enabled && (
|
{instance?.config?.is_google_enabled && (
|
||||||
<div className="flex h-[42px] items-center !overflow-hidden">
|
<div className="flex h-[42px] items-center !overflow-hidden">
|
||||||
<GoogleOAuthButton text="SignIn with Google" />
|
<GoogleOAuthButton text="Sign in with Google" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{instance?.config?.is_github_enabled && <GithubOAuthButton text="SignIn with Github" />}
|
{instance?.config?.is_github_enabled && <GithubOAuthButton text="Sign in with Github" />}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||||
import { Tooltip } from "@plane/ui";
|
import { Tooltip } from "@plane/ui";
|
||||||
// ui
|
// ui
|
||||||
import { ReactionSelector } from "@/components/ui";
|
import { ReactionSelector } from "@/components/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { groupReactions, renderEmoji } from "@/helpers/emoji.helper";
|
import { groupReactions, renderEmoji } from "@/helpers/emoji.helper";
|
||||||
|
import { queryParamGenerator } from "@/helpers/query-param-generator";
|
||||||
// hooks
|
// hooks
|
||||||
import { useIssueDetails, useUser } from "@/hooks/store";
|
import { useIssueDetails, useUser } from "@/hooks/store";
|
||||||
|
|
||||||
@ -15,6 +17,15 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const CommentReactions: React.FC<Props> = observer((props) => {
|
export const CommentReactions: React.FC<Props> = observer((props) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const pathName = usePathname();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
// query params
|
||||||
|
const board = searchParams.get("board") || undefined;
|
||||||
|
const state = searchParams.get("state") || undefined;
|
||||||
|
const priority = searchParams.get("priority") || undefined;
|
||||||
|
const labels = searchParams.get("labels") || undefined;
|
||||||
|
|
||||||
const { commentId, projectId, workspaceSlug } = props;
|
const { commentId, projectId, workspaceSlug } = props;
|
||||||
// hooks
|
// hooks
|
||||||
const { addCommentReaction, removeCommentReaction, details, peekId } = useIssueDetails();
|
const { addCommentReaction, removeCommentReaction, details, peekId } = useIssueDetails();
|
||||||
@ -42,13 +53,15 @@ export const CommentReactions: React.FC<Props> = observer((props) => {
|
|||||||
else handleAddReaction(reactionHex);
|
else handleAddReaction(reactionHex);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: on onclick redirect to login page if the user is not logged in
|
// derived values
|
||||||
|
const { queryParam } = queryParamGenerator({ peekId, board, state, priority, labels });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-2 flex items-center gap-1.5">
|
<div className="mt-2 flex items-center gap-1.5">
|
||||||
<ReactionSelector
|
<ReactionSelector
|
||||||
onSelect={(value) => {
|
onSelect={(value) => {
|
||||||
if (user) handleReactionClick(value);
|
if (user) handleReactionClick(value);
|
||||||
// userStore.requiredLogin(() => {});
|
else router.push(`/?next_path=${pathName}?${queryParam}`);
|
||||||
}}
|
}}
|
||||||
position="top"
|
position="top"
|
||||||
selected={userReactions?.map((r) => r.reaction)}
|
selected={userReactions?.map((r) => r.reaction)}
|
||||||
@ -77,7 +90,7 @@ export const CommentReactions: React.FC<Props> = observer((props) => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (user) handleReactionClick(reaction);
|
if (user) handleReactionClick(reaction);
|
||||||
// userStore.requiredLogin(() => {});
|
else router.push(`/?next_path=${pathName}?${queryParam}`);
|
||||||
}}
|
}}
|
||||||
className={`flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100 ${
|
className={`flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100 ${
|
||||||
commentReactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
|
commentReactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||||
// lib
|
// lib
|
||||||
import { Tooltip } from "@plane/ui";
|
import { Tooltip } from "@plane/ui";
|
||||||
import { ReactionSelector } from "@/components/ui";
|
import { ReactionSelector } from "@/components/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { groupReactions, renderEmoji } from "@/helpers/emoji.helper";
|
import { groupReactions, renderEmoji } from "@/helpers/emoji.helper";
|
||||||
|
import { queryParamGenerator } from "@/helpers/query-param-generator";
|
||||||
// hooks
|
// hooks
|
||||||
import { useIssueDetails, useUser } from "@/hooks/store";
|
import { useIssueDetails, useUser } from "@/hooks/store";
|
||||||
|
|
||||||
@ -14,6 +16,16 @@ type IssueEmojiReactionsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const IssueEmojiReactions: React.FC<IssueEmojiReactionsProps> = observer((props) => {
|
export const IssueEmojiReactions: React.FC<IssueEmojiReactionsProps> = observer((props) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const pathName = usePathname();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
// query params
|
||||||
|
const peekId = searchParams.get("peekId") || undefined;
|
||||||
|
const board = searchParams.get("board") || undefined;
|
||||||
|
const state = searchParams.get("state") || undefined;
|
||||||
|
const priority = searchParams.get("priority") || undefined;
|
||||||
|
const labels = searchParams.get("labels") || undefined;
|
||||||
|
|
||||||
const { workspaceSlug, projectId } = props;
|
const { workspaceSlug, projectId } = props;
|
||||||
// store
|
// store
|
||||||
const issueDetailsStore = useIssueDetails();
|
const issueDetailsStore = useIssueDetails();
|
||||||
@ -46,13 +58,15 @@ export const IssueEmojiReactions: React.FC<IssueEmojiReactionsProps> = observer(
|
|||||||
fetchCurrentUser();
|
fetchCurrentUser();
|
||||||
}, [user, fetchCurrentUser]);
|
}, [user, fetchCurrentUser]);
|
||||||
|
|
||||||
// TODO: on onclick of reaction, if user not logged in redirect to login page
|
// derived values
|
||||||
|
const { queryParam } = queryParamGenerator({ peekId, board, state, priority, labels });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ReactionSelector
|
<ReactionSelector
|
||||||
onSelect={(value) => {
|
onSelect={(value) => {
|
||||||
if (user) handleReactionClick(value);
|
if (user) handleReactionClick(value);
|
||||||
// userStore.requiredLogin(() => {});
|
else router.push(`/?next_path=${pathName}?${queryParam}`);
|
||||||
}}
|
}}
|
||||||
selected={userReactions?.map((r) => r.reaction)}
|
selected={userReactions?.map((r) => r.reaction)}
|
||||||
size="md"
|
size="md"
|
||||||
@ -80,7 +94,7 @@ export const IssueEmojiReactions: React.FC<IssueEmojiReactionsProps> = observer(
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (user) handleReactionClick(reaction);
|
if (user) handleReactionClick(reaction);
|
||||||
// userStore.requiredLogin(() => {});
|
else router.push(`/?next_path=${pathName}?${queryParam}`);
|
||||||
}}
|
}}
|
||||||
className={`flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100 ${
|
className={`flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100 ${
|
||||||
reactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
|
reactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
|
||||||
|
@ -2,11 +2,24 @@
|
|||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||||
import { Tooltip } from "@plane/ui";
|
import { Tooltip } from "@plane/ui";
|
||||||
|
// helpers
|
||||||
|
import { queryParamGenerator } from "@/helpers/query-param-generator";
|
||||||
// hooks
|
// hooks
|
||||||
import { useIssueDetails, useUser } from "@/hooks/store";
|
import { useIssueDetails, useUser } from "@/hooks/store";
|
||||||
|
|
||||||
export const IssueVotes: React.FC = observer((props: any) => {
|
export const IssueVotes: React.FC = observer((props: any) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const pathName = usePathname();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
// query params
|
||||||
|
const peekId = searchParams.get("peekId") || undefined;
|
||||||
|
const board = searchParams.get("board") || undefined;
|
||||||
|
const state = searchParams.get("state") || undefined;
|
||||||
|
const priority = searchParams.get("priority") || undefined;
|
||||||
|
const labels = searchParams.get("labels") || undefined;
|
||||||
|
|
||||||
const { workspaceSlug, projectId } = props;
|
const { workspaceSlug, projectId } = props;
|
||||||
// states
|
// states
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
@ -49,6 +62,9 @@ export const IssueVotes: React.FC = observer((props: any) => {
|
|||||||
|
|
||||||
const VOTES_LIMIT = 1000;
|
const VOTES_LIMIT = 1000;
|
||||||
|
|
||||||
|
// derived values
|
||||||
|
const { queryParam } = queryParamGenerator({ peekId, board, state, priority, labels });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{/* upvote button 👇 */}
|
{/* upvote button 👇 */}
|
||||||
@ -74,7 +90,7 @@ export const IssueVotes: React.FC = observer((props: any) => {
|
|||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (user) handleVote(e, 1);
|
if (user) handleVote(e, 1);
|
||||||
// userStore.requiredLogin(() => {});
|
else router.push(`/?next_path=${pathName}?${queryParam}`);
|
||||||
}}
|
}}
|
||||||
className={`flex items-center justify-center gap-x-1 overflow-hidden rounded border px-2 focus:outline-none ${
|
className={`flex items-center justify-center gap-x-1 overflow-hidden rounded border px-2 focus:outline-none ${
|
||||||
isUpVotedByUser ? "border-custom-primary-200 text-custom-primary-200" : "border-custom-border-300"
|
isUpVotedByUser ? "border-custom-primary-200 text-custom-primary-200" : "border-custom-border-300"
|
||||||
@ -108,7 +124,7 @@ export const IssueVotes: React.FC = observer((props: any) => {
|
|||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (user) handleVote(e, -1);
|
if (user) handleVote(e, -1);
|
||||||
// userStore.requiredLogin(() => {});
|
else router.push(`/?next_path=${pathName}?${queryParam}`);
|
||||||
}}
|
}}
|
||||||
className={`flex items-center justify-center gap-x-1 overflow-hidden rounded border px-2 focus:outline-none ${
|
className={`flex items-center justify-center gap-x-1 overflow-hidden rounded border px-2 focus:outline-none ${
|
||||||
isDownVotedByUser ? "border-red-600 text-red-600" : "border-custom-border-300"
|
isDownVotedByUser ? "border-red-600 text-red-600" : "border-custom-border-300"
|
||||||
|
Loading…
Reference in New Issue
Block a user