diff --git a/DirectReport/browserview/auth/routes.py b/DirectReport/browserview/auth/routes.py index bb159ef3..23539cfb 100644 --- a/DirectReport/browserview/auth/routes.py +++ b/DirectReport/browserview/auth/routes.py @@ -71,6 +71,7 @@ def account_data(): "username": current_user.username, "email": current_user.email, "github_username": current_user.github_username, + "github_repo": current_user.github_repo } user_element = {"user": user_account, "reports": report_results, "shortlog": shortlog} return user_element, 201 diff --git a/DirectReport/browserview/dashboard/routes.py b/DirectReport/browserview/dashboard/routes.py index 1d89e47d..6059bcda 100644 --- a/DirectReport/browserview/dashboard/routes.py +++ b/DirectReport/browserview/dashboard/routes.py @@ -9,6 +9,7 @@ from DirectReport.browserview.services.github import GithubClient from DirectReport.browserview.services.huggingface_client import HuggingFaceClient from DirectReport.browserview.services.googleai_client import GoogleAIClient +from DirectReport.browserview.services.prompt_logic import generate_email, team_summary_from_shortlog from DirectReport.models.report.report_model import ReportModel from DirectReport.datadependencies import appsecrets @@ -55,13 +56,27 @@ def dashboard_reports_update(): client = GithubClient() h_token = session['header_token'] user_repos = client.get_user_repos(current_user.github_username, h_token) + commits_last_month = client.get_commits_in_last_month(current_user.github_username, current_user.github_repo, h_token) + commits_last_sixty = client.get_commits_in_last_sixty_days(current_user.github_username, current_user.github_repo, h_token) + commits_last_ninety = client.get_commits_in_last_ninety_days(current_user.github_username, current_user.github_repo, h_token) + get_pull_requests_count = client.get_pull_requests_count(current_user.github_username, current_user.github_repo, h_token) + get_pull_requests_count_sixty = client.get_pull_requests_count_sixty_days(current_user.github_username, current_user.github_repo, h_token) repo_data = [] for repo in user_repos: repo_data.append(repo["name"]) - raw_data = googleAi.get_data_from(prompt) - begin, end = raw_data.find('{'), raw_data.rfind('}') - filtered_str = raw_data[begin : end + 1] - response_data = json.loads(filtered_str) + raw_data = team_summary_from_shortlog(prompt) + print(raw_data) + raw_reponse = raw_data["choices"][0]["message"]["content"] + response_data = json.loads(raw_reponse) + # print(response_data) + # list(raw_data.choices)[0] + # my_openai_obj.to_dict()['message']['content'] + # response_data = json.loads(raw_data) + # response_data = json.dumps(raw_data) + # raw_data = googleAi.get_data_from(prompt) + # begin, end = raw_data.find('{'), raw_data.rfind('}') + # filtered_str = raw_data[begin: end + 1] + # response_data = json.loads(filtered_str) response_data["broad_categories"] = { "debug_info": 16, "code_maintenance": 9, @@ -71,6 +86,8 @@ def dashboard_reports_update(): "readme_update": 1, "syntax_fix": 1, } + response_data["commit_nums"] = {"15 days": 4, "30 days": (commits_last_month / 10), "60 days": (commits_last_sixty / 10), "90 days": (commits_last_ninety / 10), "120 days": 30} + response_data["pull_requests"] = {"30 days": 5, "60 days": 10, "90 days": 15, "120 days": 20, "150 days": 20, "1 year": 30} response_data["repos"] = repo_data ReportBuilder.new(response_data, prompt, current_user.id, "DirectReport") return response_data, 201 diff --git a/DirectReport/browserview/main/routes.py b/DirectReport/browserview/main/routes.py index dd4073b9..4c880709 100644 --- a/DirectReport/browserview/main/routes.py +++ b/DirectReport/browserview/main/routes.py @@ -20,6 +20,8 @@ def before_request(): if current_user.is_authenticated: print("authenticated user") + print(current_user.github_username) + print(current_user.github_repo) else: print("unauthenticated user") @@ -60,8 +62,11 @@ def get_commits_last_month(repo_name): @bp.route('/repo', methods=['GET', 'POST']) def reponame(): args_url = request.args.get('repo_url') + repo = args_url.split('/')[1] h_token = session['header_token'] repo_name = "https://api.github.com/repos/" + args_url + "/commits" + user_model = UserModel() + user_model.update_github_repo(current_user.email, repo) headers = { 'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + h_token, diff --git a/DirectReport/browserview/services/github.py b/DirectReport/browserview/services/github.py index 5b04a10d..a1a9fe52 100644 --- a/DirectReport/browserview/services/github.py +++ b/DirectReport/browserview/services/github.py @@ -3,7 +3,7 @@ import re import requests from DirectReport.datadependencies import appsecrets, prompts - +from datetime import datetime, timedelta class GithubClient: # Define a function to parse the git shortlog @@ -45,7 +45,7 @@ def get_pull_request_comments(self, repo_owner, repo_name): response.raise_for_status() return response.json() - def get_pull_requests_count(self, repo_owner, repo_name): + def get_pull_requests_count(self, repo_owner, repo_name, token): """ Gets the number of comments on a pull request. @@ -58,11 +58,64 @@ def get_pull_requests_count(self, repo_owner, repo_name): The number of comments on the pull request. """ + current_date = datetime.now() + thirty_days_ago = datetime.now() - timedelta(days=30) + since = thirty_days_ago.isoformat() url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls" headers = {"Authorization": f"token {appsecrets.GITHUB_TOKEN}"} - response = requests.get(url, headers=headers) - response.raise_for_status() - return len(response.json()) + commits_count = 0 + page = 1 + per_page = 100 # Number of results per page + while True: + # Make a request to the GitHub API + response = requests.get(url, headers=headers, params={'since': since, 'page': page, 'per_page': per_page}) + response.raise_for_status() + if response.status_code != 200: + # Break the loop if the response is not successful + break + commits = response.json() + current_count = len(commits) + commits_count += current_count + if current_count < per_page: + break + page += 1 + return commits_count + + def get_pull_requests_count_sixty_days(self, repo_owner, repo_name, token): + """ + Gets the number of comments on a pull request. + + Args: + repo_owner: The owner of the GitHub repository. + repo_name: The name of the GitHub repository. + pull_request_number: The number of the pull request. + + Returns: + The number of comments on the pull request. + """ + + current_date = datetime.now() + thirty_days_ago = datetime.now() - timedelta(days=60) + since = thirty_days_ago.isoformat() + url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls" + headers = {"Authorization": f"token {appsecrets.GITHUB_TOKEN}"} + commits_count = 0 + page = 1 + per_page = 100 # Number of results per page + while True: + # Make a request to the GitHub API + response = requests.get(url, headers=headers, params={'since': since, 'page': page, 'per_page': per_page}) + response.raise_for_status() + if response.status_code != 200: + # Break the loop if the response is not successful + break + commits = response.json() + current_count = len(commits) + commits_count += current_count + if current_count < per_page: + break + page += 1 + return commits_count def get_user_repos(self, repo_owner, token): url = f"https://api.github.com/users/{repo_owner}/repos?sort=updated&order=desc" @@ -71,9 +124,79 @@ def get_user_repos(self, repo_owner, token): response.raise_for_status() return response.json() - def get_repo_issues(self, repo_owner, repo_name): + def get_repo_issues(self, repo_owner, repo_name, token): headers = {"Authorization": f"token {appsecrets.GITHUB_TOKEN}"} url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/issues" response = requests.get(url, headers=headers) response.raise_for_status() return response.json() + + def get_commits_in_last_month(self, repo_owner, repo_name, token): + current_date = datetime.now() + thirty_days_ago = datetime.now() - timedelta(days=30) + since = thirty_days_ago.isoformat() + headers = {"Authorization": f"token {token}"} + url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits" + commits_count = 0 + page = 1 + per_page = 100 # Number of results per page + while True: + # Make a request to the GitHub API + response = requests.get(url, headers=headers, params={'since': since, 'page': page, 'per_page': per_page}) + if response.status_code != 200: + # Break the loop if the response is not successful + break + commits = response.json() + current_count = len(commits) + commits_count += current_count + if current_count < per_page: + break + page += 1 + return commits_count + + def get_commits_in_last_sixty_days(self, repo_owner, repo_name, token): + current_date = datetime.now() + sixty_days_ago = datetime.now() - timedelta(days=60) + since = sixty_days_ago.isoformat() + headers = {"Authorization": f"token {token}"} + url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits" + commits_count = 0 + page = 1 + per_page = 100 # Number of results per page + while True: + # Make a request to the GitHub API + response = requests.get(url, headers=headers, params={'since': since, 'page': page, 'per_page': per_page}) + if response.status_code != 200: + # Break the loop if the response is not successful + break + commits = response.json() + current_count = len(commits) + commits_count += current_count + if current_count < per_page: + break + page += 1 + return commits_count + + def get_commits_in_last_ninety_days(self, repo_owner, repo_name, token): + current_date = datetime.now() + ninety_days_ago = datetime.now() - timedelta(days=90) + since = ninety_days_ago.isoformat() + headers = {"Authorization": f"token {token}"} + url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits" + commits_count = 0 + page = 1 + per_page = 100 # Number of results per page + while True: + # Make a request to the GitHub API + response = requests.get(url, headers=headers, params={'since': since, 'page': page, 'per_page': per_page}) + if response.status_code != 200: + # Break the loop if the response is not successful + break + commits = response.json() + current_count = len(commits) + commits_count += current_count + if current_count < per_page: + break + page += 1 + return commits_count + diff --git a/DirectReport/browserview/static/js/account/account_components.js b/DirectReport/browserview/static/js/account/account_components.js index 9d02c83a..44568cf4 100644 --- a/DirectReport/browserview/static/js/account/account_components.js +++ b/DirectReport/browserview/static/js/account/account_components.js @@ -63,14 +63,15 @@ const AccountUserInfo = (userData, reportData) => { diff --git a/DirectReport/browserview/static/js/auth/login.js b/DirectReport/browserview/static/js/auth/login.js index 55a45e62..32ffa15a 100644 --- a/DirectReport/browserview/static/js/auth/login.js +++ b/DirectReport/browserview/static/js/auth/login.js @@ -5,19 +5,19 @@ const LoginForm = () => {
-

- Sign in to your account +

+ Sign into your account

- - + +
-
@@ -27,11 +27,11 @@ const LoginForm = () => { Forgot password?
-

Don’t have an account yet? - Sign up + Sign up

diff --git a/DirectReport/browserview/static/js/auth/signup.js b/DirectReport/browserview/static/js/auth/signup.js index d44bbb6d..93915713 100644 --- a/DirectReport/browserview/static/js/auth/signup.js +++ b/DirectReport/browserview/static/js/auth/signup.js @@ -19,10 +19,10 @@ const RememberMe = () => { const NameElement = (forHtml, labelText, name, id, placeholder) => { return (
-
) } @@ -31,17 +31,17 @@ const SignupForm = () => { return (
-
{NameElement("firstname", "First name", "firstname", "firstname", "John")} {NameElement("lastname", "Last name", "lastname", "lastname", "Doe")} {NameElement("username", "Username", "username", "username", "JohnDoe")}
- - + +
{RememberMe()} @@ -56,7 +56,7 @@ const SignupForm = () => { const Signup = () => { return (
-
+

diff --git a/DirectReport/browserview/static/js/chart_helper.js b/DirectReport/browserview/static/js/chart_helper.js index c4ec570d..cd371eae 100644 --- a/DirectReport/browserview/static/js/chart_helper.js +++ b/DirectReport/browserview/static/js/chart_helper.js @@ -1,12 +1,35 @@ + +function sortOnKeys(dict) { + + var sorted = []; + for(var key in dict) { + sorted[sorted.length] = key; + } + sorted.sort(); + + var tempDict = {}; + for(var i = 0; i < sorted.length; i++) { + tempDict[sorted[i]] = dict[sorted[i]]; + } + + return tempDict; +} + + +function showAllGraphics(data, divTag, divTag2, divTag3) { + showGraphics(data, divTag); + showGraphics2(data, divTag2); + showGraphics3(data, divTag3); +} function showGraphics(data, divtag) { const newData = data + const dict = sortOnKeys(newData['pull_requests']); + const stringData = JSON.stringify(dict); - const stringData = JSON.stringify(newData['broad_categories']); - - const values = Object.keys(newData['broad_categories']).map(function (key) { - return [key, Number(newData['broad_categories'][key])] + const values = Object.keys(dict).map(function (key) { + return [key, Number(newData['pull_requests'][key])] }); const chartWidth = 350 @@ -21,7 +44,7 @@ function showGraphics(data, divtag) { .attr('width', chartWidth) .attr('height', chartHeight) - var svg = d3.select("svg") + var svg = d3.select(divtag).select("svg") var groups = svg.selectAll(".groups") .data(data) .enter() @@ -45,7 +68,7 @@ function showGraphics(data, divtag) { .attr("height", function (value, index) { return value[1] * 20 }) - .attr("fill", "teal"); + .attr("fill", "blueviolet"); groups.append("text") .attr('x', function (value, index) { @@ -57,7 +80,7 @@ function showGraphics(data, divtag) { }) .attr('y', function (value, index) { - return (chartHeight + 10) + return (chartHeight + 5) }) .attr("dy", "-1em") .style("font-size", "11px") @@ -70,12 +93,16 @@ function showGraphics(data, divtag) { function showGraphics2(data, divtag) { const newData = data + const stringData = JSON.stringify(newData['commit_nums']); - const stringData = JSON.stringify(newData['broad_categories']); - - const values = Object.keys(newData['broad_categories']).map(function (key) { - return [key, Number(newData['broad_categories'][key])] + const values = Object.keys(newData['commit_nums']).map(function (key) { + return [key, Number(newData['commit_nums'][key])] }); + // const stringData = JSON.stringify(newData['broad_categories']); + // + // const values = Object.keys(newData['broad_categories']).map(function (key) { + // return [key, Number(newData['broad_categories'][key])] + // }); const chartWidth = 350 const chartHeight = 300 @@ -201,6 +228,81 @@ function showGraphics3(data, divtag) { return value[0].split("_")[0].slice(0, 6) }) } + + +function chart4(data) { + + const newData = data + + const stringData = JSON.stringify(newData['broad_categories']); + + const values = Object.keys(newData['broad_categories']).map(function (key) { + return [key, Number(newData['broad_categories'][key])] + }); + + const width = 928; + const height = Math.min(width, 500); + + // Create the color scale. + const color = d3.scaleOrdinal() + .domain(data.map(d => d.name)) + .range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), data.length).reverse()) + + // Create the pie layout and arc generator. + const pie = d3.pie() + .sort(null) + .value(d => d.value); + + const arc = d3.arc() + .innerRadius(0) + .outerRadius(Math.min(width, height) / 2 - 1); + + const labelRadius = arc.outerRadius()() * 0.8; + + // A separate arc generator for labels. + const arcLabel = d3.arc() + .innerRadius(labelRadius) + .outerRadius(labelRadius); + + const arcs = pie(data); + + // Create the SVG container. + const svg = d3.create("svg") + .attr("width", width) + .attr("height", height) + .attr("viewBox", [-width / 2, -height / 2, width, height]) + .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;"); + + // Add a sector path for each value. + svg.append("g") + .attr("stroke", "white") + .selectAll() + .data(arcs) + .join("path") + .attr("fill", d => color(d.data.name)) + .attr("d", arc) + .append("title") + .text(d => `${d.data.name}: ${d.data.value.toLocaleString("en-US")}`); + + // Create a new arc generator to place a label close to the edge. + // The label shows the value if there is enough room. + svg.append("g") + .attr("text-anchor", "middle") + .selectAll() + .data(arcs) + .join("text") + .attr("transform", d => `translate(${arcLabel.centroid(d)})`) + .call(text => text.append("tspan") + .attr("y", "-0.4em") + .attr("font-weight", "bold") + .text(d => d.data.name)) + .call(text => text.filter(d => (d.endAngle - d.startAngle) > 0.25).append("tspan") + .attr("x", 0) + .attr("y", "0.7em") + .attr("fill-opacity", 0.7) + .text(d => d.data.value.toLocaleString("en-US"))); + return svg.node(); +} function getMax(collection) { var max = 0 collection.forEach(function (element) { diff --git a/DirectReport/browserview/static/js/index.js b/DirectReport/browserview/static/js/index.js index cd8bae74..8464198f 100644 --- a/DirectReport/browserview/static/js/index.js +++ b/DirectReport/browserview/static/js/index.js @@ -30,7 +30,7 @@ class Home extends React.Component { { className: "mt-4 text-lg mb-11 text-gray-200" }, - "Keep track of your accomplishments each day of the workweek." + "Keep track of your team's progress with DirectReport." ), React.createElement( "div", diff --git a/DirectReport/browserview/static/js/list/list_components.js b/DirectReport/browserview/static/js/list/list_components.js index 16842f1c..c963b23d 100644 --- a/DirectReport/browserview/static/js/list/list_components.js +++ b/DirectReport/browserview/static/js/list/list_components.js @@ -1,5 +1,24 @@ const { useState, useEffect } = React; +const SavedReportDiv = (item) => { + console.log(item); + return ( + + ) +} + class SavedReportList extends React.Component { render() { return ( @@ -9,16 +28,7 @@ class SavedReportList extends React.Component {

{this.props.listdata.map(item => - + )}
diff --git a/DirectReport/browserview/static/js/teamreport/teamreport.js b/DirectReport/browserview/static/js/teamreport/teamreport.js index e6301b36..1d557080 100644 --- a/DirectReport/browserview/static/js/teamreport/teamreport.js +++ b/DirectReport/browserview/static/js/teamreport/teamreport.js @@ -1,6 +1,84 @@ 'use strict'; -const { useState, useCallback, useEffect } = React; +const {useState, useCallback, useEffect} = React; + +const GetRepoListElement = (li) => { + li.classList.add("py-5"); + li.classList.add("px-3"); + li.classList.add("border-b"); + li.classList.add("border-solid"); + li.classList.add("border-blueGray-100"); +} +const GetResults = (result) => { + const results = result.data['json_array'].map((commit) => { + return { + 'message': commit['commit']['message'], + 'name': commit['commit']['author']['name'], + 'author_url': commit['author']['html_url'], + 'author_name': commit['author']['login'], + 'commit_author_email': commit['commit']['author']['email'], + 'commit_author_name': commit['commit']['author']['name'], + 'commit_author_date': commit['commit']['author']['date'], + 'committer': commit['commit']['committer']['name'], + 'committer_data': commit['commit']['committer']['date'], + 'committer_email': commit['commit']['committer']['email'], + 'comment_count': commit['commit']['comment_count'], + 'type': 'commit' + } + }) + return results +} + +const GithubEntryElement = (commits) => { + return ( +
+ {commits.length > 0 && ( +
+ {commits.map((commit) => { + return ( +
+ {GithubEntry(commit)} +
+ ) + })} +
+ )} +
+ ) +} + +const EditSummaryElem = (commits, repos, state, repoSelected, openRepoPopover) => { + return ( +
+
+

+ Github Data +

+ {GithubEntryElement(commits)} +
+
+ {repos.length > 0 && ( + + )} +
+
+
+
+ ) +} + class TeamReport extends React.Component { constructor(props) { @@ -11,7 +89,8 @@ class TeamReport extends React.Component { repos: [], reportData: {}, commits: [], - commentText: '' + commentText: '', + repoSelected: false } this.handleTeamDataChange = this.handleTeamDataChange.bind(this); @@ -20,9 +99,10 @@ class TeamReport extends React.Component { this.getRepoData = this.getRepoData.bind(this); this.handleRepoDataChange = this.handleRepoDataChange.bind(this); this.setCommits = this.setCommits.bind(this); - this.toggle = this.toggle.bind(this); + this.toggle = this.toggle.bind(this); this.toggleHide = this.toggleHide.bind(this); this.setComments = this.setComments.bind(this); + this.setRepoSelected = this.setRepoSelected.bind(this); this.handleReportDataChange = this.handleReportDataChange.bind(this); } @@ -54,9 +134,13 @@ class TeamReport extends React.Component { this.setState({repos: repoD}); } + setRepoSelected(repoSelected) { + document.getElementById('popover-repo-left-purple').classList.toggle("hidden"); + this.setState({repoSelected: repoSelected}); + } + handleSubmit() { const payload = {"prompt": this.state.commentText}; - console.log(payload); axios({ method: 'post', url: '/dashboard/reports/update', @@ -68,10 +152,9 @@ class TeamReport extends React.Component { }).then(result => { this.handleTeamDataChange(result.data["team"]); this.handleReportDataChange(result.data["report"]); - showGraphics(result.data, '#map-container'); - showGraphics2(result.data, '#map-container2'); - showGraphics3(result.data, '#map-container3'); + showAllGraphics(result.data, '#map-container', '#map-container2', '#map-container3'); this.toggle() + document.getElementById('popLefPurple').classList.toggle("hidden"); }).catch(function (response) { console.log(response); }); @@ -81,7 +164,6 @@ class TeamReport extends React.Component { this.getRepoData(); } - getRepoData() { axios({ method: 'get', @@ -91,7 +173,6 @@ class TeamReport extends React.Component { "Content-Type": "application/json" } }).then(result => { - console.log(result.data); this.handleRepoDataChange(result.data); }).catch(function (response) { console.log(response); @@ -104,34 +185,15 @@ class TeamReport extends React.Component { url: "/repo" + repoURL, headers: {'content-type': 'application/json'} }).then(result => { - console.log("result"); - console.log(result.data['result_log']); - this.setComments(result.data['result_log']); - const results = result.data['json_array'].map((commit) => { - return { - 'message': commit['commit']['message'], - 'name': commit['commit']['author']['name'], - 'author_url': commit['author']['html_url'], - 'author_name': commit['author']['login'], - 'commit_author_email': commit['commit']['author']['email'], - 'commit_author_name': commit['commit']['author']['name'], - 'commit_author_date': commit['commit']['author']['date'], - 'committer': commit['commit']['committer']['name'], - 'committer_data': commit['commit']['committer']['date'], - 'committer_email': commit['commit']['committer']['email'], - 'comment_count': commit['commit']['comment_count'], - 'type': 'commit' - } - }) + const results = GetResults(result); const prompt = results.map((commit) => { return commit.name + " " + commit.message + " " + commit.commit_author_date + "\n" }) const news = prompt.reduce((a, b) => a + b, ''); - console.log(prompt); this.setComments(news); this.setCommits(results); - console.log(results) this.handleSubmit(); + document.getElementById('popLefPurple').classList.toggle("hidden"); }).catch(error => { console.log(error); }) @@ -150,14 +212,10 @@ class TeamReport extends React.Component { var li = document.createElement("li"); var repoURL = repo["url_repo"].substring(28, repo['url'].length).replace("/", "?repo_url=") li.innerHTML = '' + repo["name"] + '' - li.classList.add("py-5"); - li.classList.add("px-3"); - li.classList.add("border-b"); - li.classList.add("border-solid"); - li.classList.add("border-blueGray-100"); + {GetRepoListElement(li, repo)} li.onclick = () => { this.update(repoURL); - document.getElementById('popover-repo-left-purple').classList.toggle("hidden"); + this.setRepoSelected(true); } list_element.append(li) }) @@ -167,79 +225,14 @@ class TeamReport extends React.Component { render() { return (
- -

- Generate Team Report From Metadata -

- +

Generate Team Report From Metadata

{repoPopoverUI()} - + {spinnerUI()}
-
-
- -

- Github Data -

- - {this.state.commits.length > 0 && ( -
- {this.state.commits.map((commit) => { - return ( -
-

{commit.message}

-

{commit.name}

-

{commit.commit_author_date}

-
- ) - })} -
- )} - -
-
- {this.state.repos.length > 0 && ( - - )} -
-
-
- -
- -
-
-

Summary

-
- {this.state.teamData.length > 0 && ( -
- {ShowSummary(this.state.reportData)} - {ShowHighlights(this.state.reportData)} -
- )} -
-
-
- -
-
-

Team

- {PopoverUI(closePopover)} - {this.state.teamData.length > 0 && ( -
- {ShowTeamList(this.state.teamData)} -
- )} -
-
+ {EditSummaryElem(this.state.commits, this.state.repos, this.state, this.state.repoSelected, this.openRepoPopover)} + {SummarySection(this.state.teamData, this.state.reportData)} + {TeamSection(this.state.teamData, this.closePopover)}
- {this.state.teamData.length <= 0 && (
@@ -247,9 +240,8 @@ class TeamReport extends React.Component { {this.state.teamData.length > 0 && ( )} -
) } -}; +} diff --git a/DirectReport/browserview/static/js/teamreport/teamreport_components.js b/DirectReport/browserview/static/js/teamreport/teamreport_components.js index f258cb0e..8f610104 100644 --- a/DirectReport/browserview/static/js/teamreport/teamreport_components.js +++ b/DirectReport/browserview/static/js/teamreport/teamreport_components.js @@ -1,8 +1,10 @@ const { useState, useEffect } = React; +// Define a functional component named 'ShowSummary' const ShowSummary = ({ report }) => { return (

+ {/* Check if 'report' and 'report.summary' are not null or undefined */} {report && report.summary &&

{report.summary} @@ -12,12 +14,15 @@ const ShowSummary = ({ report }) => { ); }; -const ShowHighlights = (report) => { +// Define a functional component named 'ShowHighlights' +const ShowHighlights = (report) => { return (
    + {/* Check if 'highlights' in report is not undefined */} {report["highlights"] !== undefined ? + // Map each highlight to an HTML structure report["highlights"].map(hightlight =>
  • @@ -27,7 +32,7 @@ const ShowHighlights = (report) => { {hightlight.description}

  • - ) : null + ) : null // Render nothing if 'highlights' is undefined }
@@ -40,15 +45,15 @@ const ShowTeamList = (team) => {
{team !== undefined ? team.map(team_member => - ) : null }
) } + const openPopover = (e: ChangeEvent, teammember) => { - // e.preventDefault(); let element = e.target; while ("BUTTON" !== element.nodeName) { element = element.parentNode; @@ -78,6 +83,74 @@ const repoPopoverUI = () => { ) } +const SummarySection = (teamData, reportData) => { + return ( + +
+
+

Summary

+
+ {teamData.length > 0 && ( +
+ {ShowSummary(reportData)} + {ShowHighlights(reportData)} +
+ )} +
+
+
+ ) +} + +const TeamSection = (teamData, closePopover) => { + return ( + +
+
+

Team

+ {PopoverUI(closePopover)} + {teamData.length > 0 && ( +
+ {ShowTeamList(teamData)} +
+ )} +
+
+ ) +} + + +const GithubEntry = (commit) => { + return ( +
+

{commit.message}

+

{commit.name}

+

{commit.commit_author_date}

+
+ ) +} + +const spinnerUI = () => { + return ( +
+
+
+
+ + Loading... +
+
+
+
+ ) +} + const closeRepoPopover = () => { document.getElementById('popover-repo-left-purple').classList.toggle("hidden"); } @@ -86,26 +159,27 @@ const closePopover = () => { document.getElementById('popover-id-left-purple').classList.toggle("hidden"); } -class GraphDiv extends React.Component { +const GraphElement = (title, id, mapcontainer_id) => { + return ( +
+

{title}

+
+
+
+
+
+
+ ) +} + +class GraphDiv extends React.Component { render() { return ( -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {GraphElement("Number of Pull Requests", "dd", "map-container")} + {GraphElement("Commits Over Times", "dd", "map-container2")} + {GraphElement("Broad Areas of Work", "dd", "map-container3")}
) } @@ -122,7 +196,8 @@ const GraphicsUI = () => { const PopoverUI = (closePopover) => { return ( -
+
diff --git a/DirectReport/browserview/templates/auth/signup.html b/DirectReport/browserview/templates/auth/signup.html index ef1c4e37..59b2cea6 100644 --- a/DirectReport/browserview/templates/auth/signup.html +++ b/DirectReport/browserview/templates/auth/signup.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block content %}
-
+
{% endblock %} \ No newline at end of file diff --git a/DirectReport/models/user_model.py b/DirectReport/models/user_model.py index 42f113bd..ba9b1bd8 100644 --- a/DirectReport/models/user_model.py +++ b/DirectReport/models/user_model.py @@ -7,7 +7,7 @@ class User(UserMixin): - def __init__(self, id, username, firstname, lastname, email, password, github_username): + def __init__(self, id, username, firstname, lastname, email, password, github_username, github_repo): self.id = email self.uid = id self.username = username @@ -17,6 +17,7 @@ def __init__(self, id, username, firstname, lastname, email, password, github_us self.password = password self.authenticated = True self.github_username = github_username + self.github_repo = github_repo def is_active(self): return True @@ -51,7 +52,8 @@ def create_table(self): lastname TEXT NOT NULL, email TEXT UNIQUE NOT NULL PRIMARY KEY, password TEXT NOT NULL, - github_username TEXT NOT NULL + github_username TEXT NOT NULL, + github_repo TEXT NOT NULL ) """ ) @@ -60,11 +62,12 @@ def create_table(self): def insert_user(self, id, username, firstname, lastname, email, password): cursor = self.conn.cursor() uuid_str = str(uuid.uuid4()) - gitub_username = "" + github_username = "" + github_repo = "" try: cursor.execute( - "INSERT INTO users (id, uid, username, firstname, lastname, email, password, github_username) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", - (id, uuid_str, username, firstname, lastname, email, password, gitub_username), + "INSERT INTO users (id, uid, username, firstname, lastname, email, password, github_username , github_repo) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + (id, uuid_str, username, firstname, lastname, email, password, github_username, github_repo), ) self.conn.commit() print("User added successfully!") @@ -74,12 +77,12 @@ def insert_user(self, id, username, firstname, lastname, email, password): def get_user_by_email(self, email): cursor = self.conn.cursor() cursor.execute( - "SELECT id, uid, username, firstname, lastname, email, password, github_username FROM users WHERE email=?", + "SELECT id, uid, username, firstname, lastname, email, password, github_username, github_repo FROM users WHERE email=?", (email,), ) result = cursor.fetchone() if result: - return User(result[0], result[2], result[3], result[4], result[5], result[6], result[7]) + return User(result[0], result[2], result[3], result[4], result[5], result[6], result[7], result[8]) return None def update_github_username(self, email, new_github_username): @@ -94,6 +97,18 @@ def update_github_username(self, email, new_github_username): except sqlite3.Error as e: print("An error occurred:", e) + def update_github_repo(self, email, new_github_repo): + cursor = self.conn.cursor() + try: + cursor.execute("UPDATE users SET github_repo = ? WHERE email = ?", (new_github_repo, email)) + self.conn.commit() + if cursor.rowcount == 0: + print("No user found with the given email.") + else: + print("GitHub username updated successfully!") + except sqlite3.Error as e: + print("An error occurred:", e) + def get_all_users(self): cursor = self.conn.cursor() cursor.execute("SELECT id, uid, username, firstname, lastname, email FROM users")