+
-
-
-
-
+
+
+
+
{% block content %} {% endblock content %}
-
-
-
+
+
diff --git a/estimation/app/templates/dashboard.html b/estimation/app/templates/dashboard.html
index e69de29..bf13d25 100644
--- a/estimation/app/templates/dashboard.html
+++ b/estimation/app/templates/dashboard.html
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/estimation/app/urls.py b/estimation/app/urls.py
index 3122f79..4c61ce9 100644
--- a/estimation/app/urls.py
+++ b/estimation/app/urls.py
@@ -1,4 +1,8 @@
from django.urls import path
from . import views
-urlpatterns = [path("", views.index, name="index")]
+urlpatterns = [path("", views.index, name="index"),
+ path('github/login/', views.github_login, name='github_login'),
+ path('github/callback/', views.github_callback, name='github_callback'),
+ path('dashboard/', views.dashboard, name='dashboard'),
+ ]
diff --git a/estimation/app/views.py b/estimation/app/views.py
index 21af73c..e94b127 100644
--- a/estimation/app/views.py
+++ b/estimation/app/views.py
@@ -1,8 +1,165 @@
-from django.http import HttpRequest
-from django.shortcuts import render
-
-# Create your views here.
+import requests
+from django.http import HttpRequest, JsonResponse
+from django.shortcuts import render, redirect
+from app.models import GithubUser
+from estimation import settings
+import re
def index(request: HttpRequest):
return render(request, "index.html", {})
+
+
+def dashboard(request):
+ avatar_url = request.session.get('avatar_url')
+ github_handle = request.session.get('github_handle')
+
+ # Clear session variables if necessary
+ request.session.pop('avatar_url', None)
+ request.session.pop('github_handle', None)
+
+ return render(request, 'dashboard.html', {
+ 'avatar_url': avatar_url,
+ 'github_handle': github_handle
+ })
+
+
+def github_login(request):
+ # GitHub OAuth authorization URL
+ github_auth_url = (
+ 'https://github.com/login/oauth/authorize?'
+ f'client_id={settings.GITHUB_CLIENT_ID}&'
+ f'redirect_uri={settings.GITHUB_REDIRECT_URI}&'
+ 'scope=repo'
+ )
+ return redirect(github_auth_url)
+
+
+def github_callback(request):
+ code = request.GET.get('code')
+ if not code:
+ return redirect('index') # Redirect to the main page if no code is present
+
+ # Exchange the authorization code for an access token
+ token_url = 'https://github.com/login/oauth/access_token'
+ payload = {
+ 'client_id': settings.GITHUB_CLIENT_ID,
+ 'client_secret': settings.GITHUB_CLIENT_SECRET,
+ 'code': code,
+ 'redirect_uri': settings.GITHUB_REDIRECT_URI,
+ }
+ headers = {'Accept': 'application/json'}
+
+ response = requests.post(token_url, data=payload, headers=headers)
+ response_data = response.json()
+
+ access_token = response_data.get('access_token')
+ if not access_token:
+ return redirect('index') # Handle the case where token is not retrieved
+
+ # Get user information from GitHub
+ user_info_url = 'https://api.github.com/user'
+ headers = {'Authorization': f'token {access_token}'}
+ user_info_response = requests.get(user_info_url, headers=headers)
+ user_info = user_info_response.json()
+
+ github_handle = user_info.get('login')
+ avatar_url = user_info.get('avatar_url')
+
+ if github_handle:
+ # Check if the user already exists in the database
+ github_user, created = GithubUser.objects.get_or_create(
+ handle=github_handle,
+ defaults={'access_token': access_token}
+ )
+
+ if not created:
+ # If the user already exists, update the access token
+ github_user.access_token = access_token
+ github_user.avatar_url = avatar_url
+ github_user.save()
+
+ print(user_info) # Optional: You can log user info for debugging
+
+ # Example values for demonstration purposes
+ project_url = 'https://github.com/users/ayeshmcg/projects/1'
+ issue_url = 'https://github.com/ayeshmcg/testRepo/issues/1'
+ story_points = 5
+
+ result = update_story_points_for_issue_card(project_url, issue_url, story_points, access_token)
+ print(result) # Log the result for debugging
+ request.session['avatar_url'] = avatar_url
+ request.session['github_handle'] = github_handle
+
+ return redirect('dashboard')
+
+
+def update_story_points_for_issue_card(project_url, issue_url, story_points, access_token):
+ # Extract project ID from the URL
+ # project_match = re.match(r'https://github.com/orgs/[^/]+/projects/(\d+)', project_url)
+ # if not project_match:
+ # return {'error': 'Invalid project URL format'}
+ #
+ # project_id = project_match.group(1)
+
+ # Extract issue number from the URL
+ # issue_match = re.match(r'https://github.com/[^/]+/[^/]+/issues/(\d+)', issue_url)
+ # if not issue_match:
+ # return {'error': 'Invalid issue URL format'}
+ #
+ # issue_number = issue_match.group(1)
+
+ # Retrieve the project columns
+ columns_url = f'https://api.github.com/projects/1/columns'
+ headers = {
+ 'Authorization': f'token {access_token}',
+ 'Accept': 'application/vnd.github+json'
+ }
+ columns_response = requests.get(columns_url, headers=headers)
+ if columns_response.status_code != 200:
+ return {'error': f'Unable to retrieve columns: {columns_response.status_code}, {columns_response.text}'}
+
+ columns = columns_response.json()
+
+ # Find the card in a column
+ card_id = None
+ for column in columns:
+ cards_url = f'https://api.github.com/projects/columns/{column["id"]}/cards'
+ cards_response = requests.get(cards_url, headers=headers)
+ if cards_response.status_code != 200:
+ return {'error': f'Unable to retrieve cards: {cards_response.status_code}, {cards_response.text}'}
+
+ cards = cards_response.json()
+ for card in cards:
+ if card.get('content_url') == issue_url:
+ card_id = card['id']
+ break
+ if card_id:
+ break
+
+ if not card_id:
+ return {'error': 'No card found for the specified issue URL'}
+
+ # Update the card with Story Points
+ card_url = f'https://api.github.com/projects/columns/cards/{card_id}'
+ card_response = requests.get(card_url, headers=headers)
+ if card_response.status_code != 200:
+ return {'error': f'Unable to retrieve card details: {card_response.status_code}, {card_response.text}'}
+
+ card_data = card_response.json()
+
+ print('card_data', card_data)
+ print('story_points', story_points)
+
+ # If the card is a note card, append the story points
+ # if 'note' in card_data:
+ # updated_note = f"{card_data['note']}\n\nStory Points: {story_points}"
+ # update_data = {'note': updated_note}
+ # else:
+ # return {'error': 'This card is not a note card and cannot be updated'}
+ #
+ # update_response = requests.patch(card_url, json=update_data, headers=headers)
+ # if update_response.status_code == 200:
+ # return {'success': 'Story Points added successfully'}
+ # else:
+ # return {'error': f'Failed to add Story Points: {update_response.status_code}'}
diff --git a/estimation/estimation/settings.py b/estimation/estimation/settings.py
index 27b5afc..42767bf 100644
--- a/estimation/estimation/settings.py
+++ b/estimation/estimation/settings.py
@@ -12,10 +12,13 @@
import os
from pathlib import Path
+from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
+load_dotenv()
+
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
@@ -120,6 +123,13 @@
USE_TZ = True
+#github details
+
+GITHUB_CLIENT_ID = os.environ.get('GITHUB_CLIENT_ID', '')
+GITHUB_CLIENT_SECRET = os.environ.get('GITHUB_CLIENT_SECRET', '')
+GITHUB_REDIRECT_URI = os.environ.get('GITHUB_REDIRECT_URI', 'http://localhost:8000/app/github/callback/')
+
+
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/
diff --git a/estimation/estimation/urls.py b/estimation/estimation/urls.py
index d08aaf4..321e2a3 100644
--- a/estimation/estimation/urls.py
+++ b/estimation/estimation/urls.py
@@ -18,7 +18,10 @@
from django.contrib import admin
from django.urls import include, path
+from app import views
+
urlpatterns = [
path("app/", include("app.urls")),
- path("admin/", admin.site.urls),
+ path("admin/", views.index),
+ # path("admin/", admin.site.urls),
]
diff --git a/requirements.txt b/requirements.txt
index ec53851..3aaf3b9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,3 +10,4 @@ requests==2.32.3
sqlparse==0.5.1
typing_extensions==4.12.2
urllib3==2.2.3
+python-dotenv~=1.0.1
\ No newline at end of file