From e4784be2cb7d86fbd141384516bffbd47630308b Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Tue, 21 Nov 2023 07:30:09 -0500 Subject: [PATCH 01/21] update next version --- DirectReport/__main__.py | 2 - DirectReport/browserview/app.py | 165 ++++++++---------- DirectReport/browserview/prompt_logic.py | 28 +++ DirectReport/browserview/static/js/account.js | 55 ++++++ DirectReport/browserview/static/js/index.js | 6 +- .../static/js/login.js} | 0 .../{__init__.py => static/js/teammember.js} | 0 .../browserview/static/js/teamreport.js | 110 +++++++++++- DirectReport/browserview/templates/base.html | 3 +- DirectReport/browserview/templates/team.html | 3 + .../browserview/templates/team_member.html | 3 + DirectReport/commandline/commandline.py | 11 -- DirectReport/models/team_member_model.py | 44 +++++ DirectReport/models/team_model.py | 48 +++++ DirectReport/models/user_model.py | 2 +- Makefile | 2 + pyproject.toml | 1 + 17 files changed, 361 insertions(+), 122 deletions(-) create mode 100644 DirectReport/browserview/prompt_logic.py rename DirectReport/{auth/app_auth.py => browserview/static/js/login.js} (100%) rename DirectReport/browserview/{__init__.py => static/js/teammember.js} (100%) create mode 100644 DirectReport/browserview/templates/team.html create mode 100644 DirectReport/browserview/templates/team_member.html create mode 100644 DirectReport/models/team_member_model.py create mode 100644 DirectReport/models/team_model.py diff --git a/DirectReport/__main__.py b/DirectReport/__main__.py index 567a1d2c..0bde0532 100644 --- a/DirectReport/__main__.py +++ b/DirectReport/__main__.py @@ -2,10 +2,8 @@ from DirectReport.commandline import commandline - def main(): commandline.cli() - if __name__ == "__main__": main() diff --git a/DirectReport/browserview/app.py b/DirectReport/browserview/app.py index a237c319..df6b72d7 100644 --- a/DirectReport/browserview/app.py +++ b/DirectReport/browserview/app.py @@ -1,16 +1,15 @@ #!/usr/bin/env python3 import flask + # Flask from flask import Flask, render_template, request, redirect, jsonify, json, url_for from werkzeug.security import generate_password_hash, check_password_hash from DirectReport.models.user_model import User, UserModel +from .prompt_logic import get_team_summarys_from_git_shortlog, generate_email from flask_login import LoginManager, login_user, login_required, logout_user, current_user -# OpenAI -import openai + import appsecrets -import prompts -openai.api_key = appsecrets.SECRET_KEY login_manager = LoginManager() app = Flask(__name__, template_folder="templates") app.secret_key = appsecrets.SECRET_KEY @@ -73,7 +72,6 @@ def user_loader(email): user = user_model.get_user_by_email(email) return user - @login_manager.request_loader def request_loader(request): email = request.form.get('email') @@ -108,71 +106,73 @@ def report(): prompt = "" if request.method == "POST": prompt = request.get_json()["prompt"] - # print(prompt) - # elements = { - # "team": [ - # { - # "name": "AdrianPrantl", - # "accomplishments": "AdrianmadesignificantcontributionstotheDebugInfoandSILGen,includingaddingsupportfordebuginfoforcoroutineallocas,inlinedandspecializedgenericvariables.Healsoworkedonthemanglingtestcase,fixedsourcelocationsofvariableassignmentsandfunctioncalls,andaddedbuild-scriptsupportforSwiftLLDBbackwards-compatibilitytests.", - # "commits": "67" - # }, - # { - # "name": "AhmadAlhashemi", - # "accomplishments": "AhmadworkedontheParser,detectingnonbreakingspaceU+00A0andprovidingafix.Healsomademinorstyleeditsandaddedmorenon-breakingspacetestcases.", - # "commits": "5" - # }, - # { - # "name": "AkshayShrimali", - # "accomplishments": "AkshayupdatedtheREADME.mdfile.", - # "commits": "1" - # }, - # { - # "name": "AlanZeino", - # "accomplishments": "AlanfixedatypointhecodeexampleinlibSyntaxREADME.", - # "commits": "1" - # }, - # { - # "name": "Albin\"albinek\"Sadowski", - # "accomplishments": "AlbinfixedsyntaxhighlightinginCHANGELOG.", - # "commits": "1" - # }, - # { - # "name": "Alejandro", - # "accomplishments": "Alejandroremovedawarning,madesomedocumentationfixes,fixedBinaryFloatingPoint.random(in:)openrangereturningupperBound,andfixedaminorcodetypoinSILPro..Man..md.", - # "commits": "3" - # }, - # { - # "name": "AlexBlewitt", - # "accomplishments": "Alexworkedonseveralfixesincludingcompareforlhsandrhs,using||insteadof&&forkindcomparison,removingduplicateconditionalcheckandduplicateifstatement.", - # "commits": "5" - # } - # ], - # "report": { - # "summary": "Theteammadesignificantprogressthisweekwithatotalof83commits.ThemainfocuswasonDebugInfoandSILGenenhancements,Parserimprovements,andvariousfixes.", - # "highlights": [ - # { - # "title": "DebugInfoandSILGenEnhancements", - # "description": "AdrianPrantlmadesignificantcontributionstotheDebugInfoandSILGen,includingaddingsupportfordebuginfoforcoroutineallocas,inlinedandspecializedgenericvariables." - # }, - # { - # "title": "ParserImprovements", - # "description": "AhmadAlhashemiworkedontheParser,detectingnonbreakingspaceU+00A0andprovidingafix." - # }, - # { - # "title": "VariousFixes", - # "description": "Theteamworkedonseveralfixesincludingcompareforlhsandrhs,using||insteadof&&forkindcomparison,removingduplicateconditionalcheckandduplicateifstatement." - # } - # ], - # "conclusion": "Theteamdemonstratedgoodprogressthisweek,withafocusonenhancingDebugInfoandSILGen,improvingtheParser,andimplementingvariousfixes.Theteamshouldcontinuetofocusontheseareasinthecomingweek." - # } - # } - elements = {} - if prompt is not "": - report = get_team_summarys_from_git_shortlog(prompt) - elements = report.choices[0].message.content - elements = elements.replace("'", '"') - elements = elements.replace('"albinek"', '') - json_object = json.loads(elements) + elements = { + "team": [ + { + "name": "AdrianPrantl", + "accomplishments": "AdrianmadesignificantcontributionstotheDebugInfoandSILGen,includingaddingsupportfordebuginfoforcoroutineallocas,inlinedandspecializedgenericvariables.Healsoworkedonthemanglingtestcase,fixedsourcelocationsofvariableassignmentsandfunctioncalls,andaddedbuild-scriptsupportforSwiftLLDBbackwards-compatibilitytests.", + "commits": "67" + }, + { + "name": "AhmadAlhashemi", + "accomplishments": "AhmadworkedontheParser,detectingnonbreakingspaceU+00A0andprovidingafix.Healsomademinorstyleeditsandaddedmorenon-breakingspacetestcases.", + "commits": "5" + }, + { + "name": "AkshayShrimali", + "accomplishments": "AkshayupdatedtheREADME.mdfile.", + "commits": "1" + }, + { + "name": "AlanZeino", + "accomplishments": "AlanfixedatypointhecodeexampleinlibSyntaxREADME.", + "commits": "1" + }, + { + "name": "Albin\"albinek\"Sadowski", + "accomplishments": "AlbinfixedsyntaxhighlightinginCHANGELOG.", + "commits": "1" + }, + { + "name": "Alejandro", + "accomplishments": "Alejandroremovedawarning,madesomedocumentationfixes,fixedBinaryFloatingPoint.random(in:)openrangereturningupperBound,andfixedaminorcodetypoinSILPro..Man..md.", + "commits": "3" + }, + { + "name": "AlexBlewitt", + "accomplishments": "Alexworkedonseveralfixesincludingcompareforlhsandrhs,using||insteadof&&forkindcomparison,removingduplicateconditionalcheckandduplicateifstatement.", + "commits": "5" + } + ], + "report": { + "summary": "Theteammadesignificantprogressthisweekwithatotalof83commits.ThemainfocuswasonDebugInfoandSILGenenhancements,Parserimprovements,andvariousfixes.", + "total_commits": "83", + "areas_of_focus": ["DebugInfoandSILGenEnhancements", "ParserImprovements", "VariousFixes"], + "highlights": [ + { + "title": "DebugInfoandSILGenEnhancements", + "description": "AdrianPrantlmadesignificantcontributionstotheDebugInfoandSILGen,includingaddingsupportfordebuginfoforcoroutineallocas,inlinedandspecializedgenericvariables." + }, + { + "title": "ParserImprovements", + "description": "AhmadAlhashemiworkedontheParser,detectingnonbreakingspaceU+00A0andprovidingafix." + }, + { + "title": "VariousFixes", + "description": "Theteamworkedonseveralfixesincludingcompareforlhsandrhs,using||insteadof&&forkindcomparison,removingduplicateconditionalcheckandduplicateifstatement." + } + ], + "conclusion": "Theteamdemonstratedgoodprogressthisweek,withafocusonenhancingDebugInfoandSILGen,improvingtheParser,andimplementingvariousfixes.Theteamshouldcontinuetofocusontheseareasinthecomingweek." + } + } + # elements = {} + # if prompt is not "": + # report = get_team_summarys_from_git_shortlog(prompt) + # elements = report.choices[0].message.content + # print(elements) + # elements = elements.replace("'", '"') + # elements = elements.replace('"albinek"', '') + # json_object = json.loads(elements) return elements, 201 @app.route("/generate_email", methods=['POST']) @@ -180,35 +180,10 @@ def generate_email(): prompt = "" if request.method == "POST": prompt = json.dumps(request.get_json()["prompt"]) - print(prompt) report = generate_email(prompt) elements = {"email": report.choices[0].message.content} return elements, 201 -def get_team_summarys_from_git_shortlog(data): - prompt = prompts.GENERATE_SUMMARY_PROMPT_PREIX + data - message=[{"role": "user", "content": prompt}] - response = openai.ChatCompletion.create( - model="gpt-4", - messages = message, - temperature=0.1, - max_tokens=1000, - frequency_penalty=0.0 - ) - return response - -def generate_email(data): - prompt = prompts.GENERATE_EMAIL_PROMPT_PREFIX + data - message=[{"role": "user", "content": prompt}] - response = openai.ChatCompletion.create( - model="gpt-4", - messages = message, - temperature=0.1, - max_tokens=1000, - frequency_penalty=0.0 - ) - return response - if __name__ == "__main__": app.run() diff --git a/DirectReport/browserview/prompt_logic.py b/DirectReport/browserview/prompt_logic.py new file mode 100644 index 00000000..ff9bbc77 --- /dev/null +++ b/DirectReport/browserview/prompt_logic.py @@ -0,0 +1,28 @@ +import openai +import prompts +import appsecrets + +openai.api_key = appsecrets.SECRET_KEY +def generate_email(data): + prompt = prompts.GENERATE_EMAIL_PROMPT_PREFIX + data + message=[{"role": "user", "content": prompt}] + response = openai.ChatCompletion.create( + model="gpt-4", + messages = message, + temperature=0.1, + max_tokens=1000, + frequency_penalty=0.0 + ) + return response + +def get_team_summarys_from_git_shortlog(data): + prompt = prompts.GENERATE_SUMMARY_PROMPT_PREIX + data + message=[{"role": "user", "content": prompt}] + response = openai.ChatCompletion.create( + model="gpt-4", + messages = message, + temperature=0, + max_tokens=1000, + frequency_penalty=0.0 + ) + return response diff --git a/DirectReport/browserview/static/js/account.js b/DirectReport/browserview/static/js/account.js index e69de29b..fb5de06e 100644 --- a/DirectReport/browserview/static/js/account.js +++ b/DirectReport/browserview/static/js/account.js @@ -0,0 +1,55 @@ +'use strict'; +const elem = React.createElement; + +class Account extends React.Component { + render() { + return elem( + 'div', + null, + React.createElement( + 'div', + { + className: "py-24 flex h-100", + style: {background: "linear-gradient(90deg, #667eea 0%, #764ba2 100%)"} + }, + React.createElement( + "div", + { + className: "container mx-auto px-6" + }, + React.createElement( + "h2", + { + className: "my-4 text-4xl font-bold mb-2 text-white" + }, + "DirectReport." + ), + React.createElement( + "h3", + { + className: "my-8 text-2xl mb-12 text-gray-200" + }, + "Keep track of your accomplishments each day of the workweek." + ), + React.createElement( + "div", + { + className: "my-8" + }, + React.createElement( + "a", + { + className: "my-12 px-14 py-5 text-lg font-bold text-center text-white bg-gray-400 rounded-full hover:bg-blue-800 shadow-lg uppercase", + href: "https://github.com/chriswebb09/DirectReport" + }, + "Github" + ) + ) + ) + ) + ); + } +} + +const domContainer = document.querySelector('#root'); +ReactDOM.render(elem(Home), domContainer); \ No newline at end of file diff --git a/DirectReport/browserview/static/js/index.js b/DirectReport/browserview/static/js/index.js index d2c7c5d8..b1343aa2 100644 --- a/DirectReport/browserview/static/js/index.js +++ b/DirectReport/browserview/static/js/index.js @@ -1,9 +1,9 @@ 'use strict'; -const e = React.createElement; +const elem = React.createElement; class Home extends React.Component { render() { - return e( + return elem( 'div', null, React.createElement( @@ -52,4 +52,4 @@ class Home extends React.Component { } const domContainer = document.querySelector('#root'); -ReactDOM.render(e(Home), domContainer); +ReactDOM.render(elem(Home), domContainer); diff --git a/DirectReport/auth/app_auth.py b/DirectReport/browserview/static/js/login.js similarity index 100% rename from DirectReport/auth/app_auth.py rename to DirectReport/browserview/static/js/login.js diff --git a/DirectReport/browserview/__init__.py b/DirectReport/browserview/static/js/teammember.js similarity index 100% rename from DirectReport/browserview/__init__.py rename to DirectReport/browserview/static/js/teammember.js diff --git a/DirectReport/browserview/static/js/teamreport.js b/DirectReport/browserview/static/js/teamreport.js index 53b2d6d1..45071ba2 100644 --- a/DirectReport/browserview/static/js/teamreport.js +++ b/DirectReport/browserview/static/js/teamreport.js @@ -1,5 +1,4 @@ const { useState, useEffect } = React; - const TeamData = () => { const [teamData, setTeamData] = useState({}); const [commentText, setCommentText] = useState("") @@ -26,6 +25,7 @@ const TeamData = () => { }).then(function(data) { setTeamData(data); toggle(); + showGraphics(); }); }; @@ -59,13 +59,83 @@ const TeamData = () => { }); } + const openPopover = e => { + e.preventDefault() + let element = e.target; + while(element.nodeName !== "BUTTON"){ + element = element.parentNode; + } + Popper.createPopper(element, document.getElementById('popover-id-left-purple'), { + strategy: 'fixed' + }); + document.getElementById('popover-id-left-purple').classList.toggle("hidden"); + } + + // function showGraphics(){ + // const mapcontainer = d3.select("#map-container"); + // mapcontainer.append("span").text("Hello, world!"); + // } + + function showGraphics() { + var dataset = [5, 10, 15, 20, 25] + +// Sizing variables for our chart. These are saved as variables as they will be used in calculations. + var chartWidth = 300 + var chartHeight = 100 + var padding = 5 + +// We want our our bars to take up the full height of the chart, so, we will apply a scaling factor to the height of every bar. + var heightScalingFactor = chartHeight / getMax(dataset) + +// Here we are creating the SVG that will be our chart. + var svg = d3 + .select('#map-container') // I'm starting off by selecting the container. + .append('svg') // Appending an SVG element to that container. + .attr('width', chartWidth) // Setting the width of the SVG. + .attr('height', chartHeight) // And setting the height of the SVG. + +// The next step is to create the rectangles that will make up the bars in our bar chart. + svg + .selectAll('rect') // I'm selecting all of the rectangles in the SVG (note that at this point, there actually aren't any, but we'll be creating them in a couple of steps). + .data(dataset) // Then I'm mapping the dataset to those rectangles. + .enter() // This step is important in that it allows us to dynamically create the rectangle elements that we selected previously. + .append('rect') // For each element in the dataset, append a new rectangle. + .attr('x', function (value, index) { // Set the X position of the rectangle by taking the index of the current item we are creating, multiplying it by the calculated width of each bar, and adding a padding value so we can see some space between bars. + return (index * (chartWidth / dataset.length)) + padding + }) + .attr('y', function (value, index) { // Set the rectangle by subtracting the scaled height from the height of the chart (this has to be done becuase SVG coordinates start with 0,0 at their top left corner). + return chartHeight - (value * heightScalingFactor) + }) + .attr('width', (chartWidth / dataset.length) - padding) // The width is dynamically calculated to have an even distribution of bars that take up the entire width of the chart. + .attr('height', function (value, index) { // The height is simply the value of the item in the dataset multiplied by the height scaling factor. + return value * heightScalingFactor + }) + .attr('fill', 'pink') // Sets the color of the bars. + + /** + * Gets the maximum value in a collection of numbers. + */ + + } + + function getMax(collection) { + var max = 0 + + collection.forEach(function (element) { + max = element > max ? element : max + }) + + return max + } + + return (

Generate Team Report From Metadata

-
+

Enter Github Data

@@ -110,26 +180,48 @@ const TeamData = () => {

Team

+
+
+
purple popover title
+
And here's some amazing content. It's very engaging. Right?
+
+
{isOpened && ( -
-
+
+
{teamData["team"] && teamData["team"].map(teammember => - + // + + // )}
)}
+
+
+
+ {/*

User Statistics

*/} + {/*{isHidden && (*/} + {/*
{generatedEmail}
*/} + {/*)}*/} + {/*{isOpened && (*/} + {/*
*/} + {/* */} + {/*
*/} + {/*)}*/} +
+
-

Generated Email

+

Generated + Email

{isHidden && ( -
- {generatedEmail} -
+
{generatedEmail}
)} {isOpened && (
diff --git a/DirectReport/browserview/templates/base.html b/DirectReport/browserview/templates/base.html index 1596afea..834da4e7 100644 --- a/DirectReport/browserview/templates/base.html +++ b/DirectReport/browserview/templates/base.html @@ -7,10 +7,11 @@ + + - diff --git a/DirectReport/browserview/templates/team.html b/DirectReport/browserview/templates/team.html new file mode 100644 index 00000000..7a19a488 --- /dev/null +++ b/DirectReport/browserview/templates/team.html @@ -0,0 +1,3 @@ +{% extends "base.html" %} +{% block content %} +{% endblock %} \ No newline at end of file diff --git a/DirectReport/browserview/templates/team_member.html b/DirectReport/browserview/templates/team_member.html new file mode 100644 index 00000000..7a19a488 --- /dev/null +++ b/DirectReport/browserview/templates/team_member.html @@ -0,0 +1,3 @@ +{% extends "base.html" %} +{% block content %} +{% endblock %} \ No newline at end of file diff --git a/DirectReport/commandline/commandline.py b/DirectReport/commandline/commandline.py index d77b17ad..c5cd5961 100644 --- a/DirectReport/commandline/commandline.py +++ b/DirectReport/commandline/commandline.py @@ -10,27 +10,22 @@ file = Path(__file__).resolve() package_root_directory = file.parents[1] sys.path.append(str(package_root_directory)) - @click.group() def cli(): """Main Click group for the command line interface.""" pass - @cli.group() def list_items(): """Click group for list items related commands.""" pass - @cli.group() def item(): """Click group for item related commands.""" pass - @cli.group() def web_browser(): """Click group for web browser related commands.""" pass - @click.command() @click.option('--day', 'transformation', flag_value='day') @click.option('--all', 'transformation', flag_value='all') @@ -48,8 +43,6 @@ def list(transformation): if all_list is not None: for all_item in all_list: print(str(all_item) + "\n") - - @click.command() @click.option('--entry', 'transformation', flag_value='entry', default=True, help="Add new entry to list") def new(transformation): @@ -62,8 +55,6 @@ def new(transformation): entry = click.prompt('Goal', type=str) ListBuilder.new(entry, topic) return - - @click.command() @click.option('--id', help="Delete item with id", prompt='What is the id of the entry you wish to delete?') def delete(uid): @@ -72,7 +63,6 @@ def delete(uid): :param uid: The ID of the item to delete. """ ListBuilder.delete(uid) - @click.command() @click.option("--url", default="http://127.0.0.1:5000", help="URL to open in the web browser") def launch(url): @@ -82,7 +72,6 @@ def launch(url): """ click.launch(url) app.run() - @click.command() def mail(): """ diff --git a/DirectReport/models/team_member_model.py b/DirectReport/models/team_member_model.py new file mode 100644 index 00000000..1e7c113c --- /dev/null +++ b/DirectReport/models/team_member_model.py @@ -0,0 +1,44 @@ +import sqlite3 +import uuid + +class TeamMember: + def __init__(self, id, team_id, username): + self.id = id + self.team_id = team_id + self.username = username + +class TeamMemberModel: + + def __init__(self, db_name="teammember.db"): + self.conn = sqlite3.connect(db_name, check_same_thread=False) + self.create_table() + + def create_table(self): + cursor = self.conn.cursor() + cursor.execute(""" + CREATE TABLE IF NOT EXISTS teammember ( + id TEXT UNIQUE NOT NULL PRIMARY KEY, + team_id TEXT NOT NULL, + username TEXT NOT NULL + ) + """) + self.conn.commit() + + def insert_team(self, team_id, username): + cursor = self.conn.cursor() + uuid_str = str(uuid.uuid4()) + try: + cursor.execute("INSERT INTO teammember (id, team_id, username) VALUES (?, ?, ?)", (uuid_str, team_id, username)) + self.conn.commit() + print("User added successfully!") + except sqlite3.IntegrityError: + print("Error: Email already exists.") + + def get_team_by_id(self, team_id): + cursor = self.conn.cursor() + cursor.execute("SELECT id, team_id, username FROM teammember WHERE team_id=?", (team_id,)) + result = cursor.fetchone() + if result: + return TeamMember(result[0], result[1], result[2]) + def close(self): + self.conn.close() diff --git a/DirectReport/models/team_model.py b/DirectReport/models/team_model.py new file mode 100644 index 00000000..bd3c764a --- /dev/null +++ b/DirectReport/models/team_model.py @@ -0,0 +1,48 @@ +import sqlite3 +import uuid + +class Team: + + def __init__(self, team_id, team_name, team_email): + self.team_id = team_id + self.team_name = team_name + self.team_email = team_email + + +class TeamModel: + + def __init__(self, db_name="team.db"): + self.conn = sqlite3.connect(db_name, check_same_thread=False) + self.create_table() + + def create_table(self): + cursor = self.conn.cursor() + cursor.execute(""" + CREATE TABLE IF NOT EXISTS team ( + id TEXT UNIQUE NOT NULL PRIMARY KEY, + team_name TEXT NOT NULL, + team_email TEXT NOT NULL + ) + """) + + + def insert_team(self, team_name, team_email): + cursor = self.conn.cursor() + uuid_str = str(uuid.uuid4()) + try: + cursor.execute("INSERT INTO team (id, team_name, team_email) VALUES (?, ?, ?)", (uuid_str, team_name, team_email)) + self.conn.commit() + print("User added successfully!") + except sqlite3.IntegrityError: + print("Error: Email already exists.") + + def get_team_by_email(self, team_email): + cursor = self.conn.cursor() + cursor.execute("SELECT id, team_name, team_email, password FROM team WHERE team_email=?", (team_email,)) + result = cursor.fetchone() + if result: + return Team(result[0], result[1], result[2]) + return None + + def close(self): + self.conn.close() diff --git a/DirectReport/models/user_model.py b/DirectReport/models/user_model.py index 5a14f788..15e36c33 100644 --- a/DirectReport/models/user_model.py +++ b/DirectReport/models/user_model.py @@ -1,7 +1,7 @@ import sqlite3 import uuid from flask_login import UserMixin - +from app import app as application class User(UserMixin): def __init__(self, id, username, email, password): diff --git a/Makefile b/Makefile index 21ebd440..4303fcd0 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,8 @@ TMPREPO=/tmp/docs/DirectReport develop: ## install dependencies and build library python3 -m pip install Flask --user python3 -m pip install Flask-Login --user + python3 -m pip install langchain --user + python3 -m pip install -e .[develop] build: ## build the python library diff --git a/pyproject.toml b/pyproject.toml index c5878aae..b37230a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ requires = [ "wheel", "Flask", "click", + "langchain", "openai", "Flask-Login", "python-Levenshtein", From 49b33ef789d7008b7a7d0e52a798c959f0ca82b8 Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Wed, 22 Nov 2023 00:16:39 -0500 Subject: [PATCH 02/21] working on user accounts --- DirectReport/__init__.py | 1 + DirectReport/browserview/app.py | 29 +- DirectReport/browserview/prompt_logic.py | 7 +- DirectReport/browserview/static/js/index.js | 12 +- .../browserview/static/js/teamreport.js | 300 ++++++++++++++++-- .../browserview/templates/_navigation.html | 10 +- .../browserview/templates/account.html | 18 +- DirectReport/browserview/templates/index.html | 4 +- DirectReport/browserview/templates/list.html | 142 +++++++++ .../browserview/templates/note.html | 0 DirectReport/datadependencies/__init__.py | 0 DirectReport/datadependencies/prompts.py | 5 + DirectReport/models/user_model.py | 2 +- prompts.py | 4 - 14 files changed, 466 insertions(+), 68 deletions(-) create mode 100644 DirectReport/browserview/templates/list.html rename secrets.py => DirectReport/browserview/templates/note.html (100%) create mode 100644 DirectReport/datadependencies/__init__.py create mode 100644 DirectReport/datadependencies/prompts.py delete mode 100644 prompts.py diff --git a/DirectReport/__init__.py b/DirectReport/__init__.py index 06cd4b2d..c012392e 100644 --- a/DirectReport/__init__.py +++ b/DirectReport/__init__.py @@ -4,5 +4,6 @@ from .browserview import * from .models import * from .tests import * +from .datadependencies import * __version__ = "1.0.0" diff --git a/DirectReport/browserview/app.py b/DirectReport/browserview/app.py index df6b72d7..8b28e38a 100644 --- a/DirectReport/browserview/app.py +++ b/DirectReport/browserview/app.py @@ -1,14 +1,13 @@ #!/usr/bin/env python3 -import flask # Flask -from flask import Flask, render_template, request, redirect, jsonify, json, url_for -from werkzeug.security import generate_password_hash, check_password_hash -from DirectReport.models.user_model import User, UserModel -from .prompt_logic import get_team_summarys_from_git_shortlog, generate_email +from flask import Flask, render_template, request, redirect, json, url_for +from werkzeug.security import generate_password_hash +from DirectReport.models.user_model import UserModel +from .prompt_logic import generate_email from flask_login import LoginManager, login_user, login_required, logout_user, current_user -import appsecrets +from DirectReport.datadependencies import appsecrets login_manager = LoginManager() app = Flask(__name__, template_folder="templates") @@ -84,6 +83,24 @@ def account(): print(current_user.is_authenticated()) return render_template('account.html', title='Account', name=current_user.username, userid=current_user.id) + +@app.route("/list", methods=['GET', 'POST']) +@login_required +def list_entries(): + """ + Retrieves and renders the list of all entries. + + :return: Rendered HTML template for the list page. + """ + # if request.method == "POST": + # json_data = request.get_json() + # ListBuilder.new(json_data["entry"], json_data["topic"]) + # week_id = WeeklyBuilder.get_weekly_id() + # week = WeeklyBuilder.list_week(week_id) + return render_template('list.html', title='List', data=[]) + + + @login_manager.unauthorized_handler def unauthorized_handler(): print("unauthorized_handler") diff --git a/DirectReport/browserview/prompt_logic.py b/DirectReport/browserview/prompt_logic.py index ff9bbc77..39045048 100644 --- a/DirectReport/browserview/prompt_logic.py +++ b/DirectReport/browserview/prompt_logic.py @@ -1,10 +1,9 @@ import openai -import prompts -import appsecrets +from DirectReport.datadependencies import appsecrets, prompts openai.api_key = appsecrets.SECRET_KEY def generate_email(data): - prompt = prompts.GENERATE_EMAIL_PROMPT_PREFIX + data + prompt = prompts.GENERATE_EMAIL_PROMPT_PREFIX + data message=[{"role": "user", "content": prompt}] response = openai.ChatCompletion.create( model="gpt-4", @@ -16,7 +15,7 @@ def generate_email(data): return response def get_team_summarys_from_git_shortlog(data): - prompt = prompts.GENERATE_SUMMARY_PROMPT_PREIX + data + prompt = prompts.GENERATE_SUMMARY_PROMPT_PREIX + data message=[{"role": "user", "content": prompt}] response = openai.ChatCompletion.create( model="gpt-4", diff --git a/DirectReport/browserview/static/js/index.js b/DirectReport/browserview/static/js/index.js index b1343aa2..fe2a5281 100644 --- a/DirectReport/browserview/static/js/index.js +++ b/DirectReport/browserview/static/js/index.js @@ -9,7 +9,7 @@ class Home extends React.Component { React.createElement( 'div', { - className: "py-24 flex h-100", + className: "py-20 flex h-50", style: {background: "linear-gradient(90deg, #667eea 0%, #764ba2 100%)"} }, React.createElement( @@ -20,14 +20,14 @@ class Home extends React.Component { React.createElement( "h2", { - className: "my-4 text-4xl font-bold mb-2 text-white" + className: "my-2 text-3xl font-bold mb-8 text-white" }, "DirectReport." ), React.createElement( "h3", { - className: "my-8 text-2xl mb-12 text-gray-200" + className: "my-3 text-lg mb-12 text-gray-200" }, "Keep track of your accomplishments each day of the workweek." ), @@ -39,10 +39,10 @@ class Home extends React.Component { React.createElement( "a", { - className: "my-12 px-14 py-5 text-lg font-bold text-center text-white bg-gray-400 rounded-full hover:bg-blue-800 shadow-lg uppercase", - href: "https://github.com/chriswebb09/DirectReport" + className: "my-12 px-10 py-5 text-lg font-bold text-center text-white bg-gray-400 rounded-full hover:bg-blue-800 shadow-lg uppercase", + href: "/account" }, - "Github" + "Get Started" ) ) ) diff --git a/DirectReport/browserview/static/js/teamreport.js b/DirectReport/browserview/static/js/teamreport.js index 45071ba2..273bc098 100644 --- a/DirectReport/browserview/static/js/teamreport.js +++ b/DirectReport/browserview/static/js/teamreport.js @@ -5,8 +5,6 @@ const TeamData = () => { const [generatedEmail, setGeneratedEmail] = useState("") const [isOpened, setIsOpened] = useState(false); const [isHidden, setIsHidden] = useState(false); - - const handleSubmit = e => { e.preventDefault() var dataForm = { @@ -79,22 +77,18 @@ const TeamData = () => { function showGraphics() { var dataset = [5, 10, 15, 20, 25] -// Sizing variables for our chart. These are saved as variables as they will be used in calculations. - var chartWidth = 300 - var chartHeight = 100 - var padding = 5 + var chartWidth = 400 + var chartHeight = 200 + var padding = 20 -// We want our our bars to take up the full height of the chart, so, we will apply a scaling factor to the height of every bar. var heightScalingFactor = chartHeight / getMax(dataset) -// Here we are creating the SVG that will be our chart. var svg = d3 .select('#map-container') // I'm starting off by selecting the container. .append('svg') // Appending an SVG element to that container. .attr('width', chartWidth) // Setting the width of the SVG. .attr('height', chartHeight) // And setting the height of the SVG. -// The next step is to create the rectangles that will make up the bars in our bar chart. svg .selectAll('rect') // I'm selecting all of the rectangles in the SVG (note that at this point, there actually aren't any, but we'll be creating them in a couple of steps). .data(dataset) // Then I'm mapping the dataset to those rectangles. @@ -131,42 +125,42 @@ const TeamData = () => { return (
-

Generate Team Report From Metadata

+

Generate Team Report From Metadata

-
-
-

Enter Github Data

+
+ +

Enter Github Data

- +
- +
-
-

Summary

-
+
+

Summary

+
{isOpened && ( -
-

+

+

{ teamData["report"] !== undefined ? -

{teamData["report"]["summary"]}
+
{teamData["report"]["summary"]}
: null }

-
    +
      {teamData["report"] && teamData["report"]["highlights"].map(hightlight =>
    • -

      {hightlight.title}

      -

      {hightlight.description}

      +

      {hightlight.title}

      +

      {hightlight.description}

    • )}
    @@ -177,8 +171,8 @@ const TeamData = () => {
-
-

+
+

Team

@@ -188,13 +182,12 @@ const TeamData = () => {
{isOpened && ( -
-
+
+
{teamData["team"] && teamData["team"].map(teammember => //
- + //
)}
@@ -204,7 +197,10 @@ const TeamData = () => {
-
+
+
+
+ {/*

User Statistics

*/} {/*{isHidden && (*/} {/*
{generatedEmail}
*/} @@ -238,3 +234,245 @@ const TeamData = () => { const domContainer = document.querySelector('#root'); ReactDOM.render(, domContainer); + + +// const { useState, useEffect } = React; +// const TeamData = () => { +// const [teamData, setTeamData] = useState({}); +// const [commentText, setCommentText] = useState("") +// const [generatedEmail, setGeneratedEmail] = useState("") +// const [isOpened, setIsOpened] = useState(false); +// const [isHidden, setIsHidden] = useState(false); +// +// +// const handleSubmit = e => { +// e.preventDefault() +// var dataForm = { +// "prompt": commentText +// }; +// const formDataJsonString = JSON.stringify(dataForm); +// fetch("/report", { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// "Accept": "application/json" +// }, +// body: formDataJsonString +// }).then(function(res) { +// return res.json(); +// }).then(function(data) { +// setTeamData(data); +// toggle(); +// showGraphics(); +// }); +// }; +// +// function toggle() { +// setIsOpened(wasOpened => !wasOpened); +// } +// +// function toggleHide() { +// setIsHidden(wasHidden => !wasHidden); +// } +// +// +// const handleClick = e => { +// e.preventDefault() +// var dataForm = { +// "prompt": JSON.stringify(teamData) +// }; +// const formDataJsonString = JSON.stringify(dataForm); +// fetch("/generate_email", { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// "Accept": "application/json" +// }, +// body: formDataJsonString +// }).then(function(res) { +// return res.json(); +// }).then(function(data) { +// setGeneratedEmail(data["email"]); +// toggleHide(); +// }); +// } +// +// const openPopover = e => { +// e.preventDefault() +// let element = e.target; +// while(element.nodeName !== "BUTTON"){ +// element = element.parentNode; +// } +// Popper.createPopper(element, document.getElementById('popover-id-left-purple'), { +// strategy: 'fixed' +// }); +// document.getElementById('popover-id-left-purple').classList.toggle("hidden"); +// } +// +// // function showGraphics(){ +// // const mapcontainer = d3.select("#map-container"); +// // mapcontainer.append("span").text("Hello, world!"); +// // } +// +// function showGraphics() { +// var dataset = [5, 10, 15, 20, 25] +// +// // Sizing variables for our chart. These are saved as variables as they will be used in calculations. +// var chartWidth = 300 +// var chartHeight = 100 +// var padding = 5 +// +// // We want our our bars to take up the full height of the chart, so, we will apply a scaling factor to the height of every bar. +// var heightScalingFactor = chartHeight / getMax(dataset) +// +// // Here we are creating the SVG that will be our chart. +// var svg = d3 +// .select('#map-container') // I'm starting off by selecting the container. +// .append('svg') // Appending an SVG element to that container. +// .attr('width', chartWidth) // Setting the width of the SVG. +// .attr('height', chartHeight) // And setting the height of the SVG. +// +// // The next step is to create the rectangles that will make up the bars in our bar chart. +// svg +// .selectAll('rect') // I'm selecting all of the rectangles in the SVG (note that at this point, there actually aren't any, but we'll be creating them in a couple of steps). +// .data(dataset) // Then I'm mapping the dataset to those rectangles. +// .enter() // This step is important in that it allows us to dynamically create the rectangle elements that we selected previously. +// .append('rect') // For each element in the dataset, append a new rectangle. +// .attr('x', function (value, index) { // Set the X position of the rectangle by taking the index of the current item we are creating, multiplying it by the calculated width of each bar, and adding a padding value so we can see some space between bars. +// return (index * (chartWidth / dataset.length)) + padding +// }) +// .attr('y', function (value, index) { // Set the rectangle by subtracting the scaled height from the height of the chart (this has to be done becuase SVG coordinates start with 0,0 at their top left corner). +// return chartHeight - (value * heightScalingFactor) +// }) +// .attr('width', (chartWidth / dataset.length) - padding) // The width is dynamically calculated to have an even distribution of bars that take up the entire width of the chart. +// .attr('height', function (value, index) { // The height is simply the value of the item in the dataset multiplied by the height scaling factor. +// return value * heightScalingFactor +// }) +// .attr('fill', 'pink') // Sets the color of the bars. +// +// /** +// * Gets the maximum value in a collection of numbers. +// */ +// +// } +// +// function getMax(collection) { +// var max = 0 +// +// collection.forEach(function (element) { +// max = element > max ? element : max +// }) +// +// return max +// } +// +// +// return ( +//
+//

Generate Team Report From Metadata

+//
+//
+//
+//
+//

Enter Github Data

+//
+//
+// +//
+//
+// +//
+//
+//
+//
+//
+//
+//
+//

Summary

+//
+// {isOpened && ( +//
+//

+// { teamData["report"] !== undefined ? +//

{teamData["report"]["summary"]}
+// : null +// } +//

+//
+//
    +// {teamData["report"] && +// teamData["report"]["highlights"].map(hightlight => +//
  • +//

    {hightlight.title}

    +//

    {hightlight.description}

    +//
  • +// )} +//
+//
+//
+// )} +//
+//
+//
+//
+//
+//

+// Team

+//
+//
+//
purple popover title
+//
And here's some amazing content. It's very engaging. Right?
+//
+//
+//
+// {isOpened && ( +//
+//
+// {teamData["team"] && +// teamData["team"].map(teammember => +// //
+// +// //
+// )} +//
+//
+// )} +//
+//
+//
+//
+//
+// {/*

User Statistics

*/} +// {/*{isHidden && (*/} +// {/*
{generatedEmail}
*/} +// {/*)}*/} +// {/*{isOpened && (*/} +// {/*
*/} +// {/* */} +// {/*
*/} +// {/*)}*/} +//
+//
+//
+//
+//

Generated +// Email

+// {isHidden && ( +//
{generatedEmail}
+// )} +// {isOpened && ( +//
+// +//
+// )} +//
+//
+//
+//
+// +// ); +// }; +// +// const domContainer = document.querySelector('#root'); +// ReactDOM.render(, domContainer); diff --git a/DirectReport/browserview/templates/_navigation.html b/DirectReport/browserview/templates/_navigation.html index 0af404ec..ad6f86c9 100644 --- a/DirectReport/browserview/templates/_navigation.html +++ b/DirectReport/browserview/templates/_navigation.html @@ -1,13 +1,11 @@

- - + + +
+
+ +
-
- - + +
- +
-
diff --git a/DirectReport/browserview/static/js/teammember.js b/DirectReport/browserview/static/js/teammember.js index a90ddd71..8c0a762c 100644 --- a/DirectReport/browserview/static/js/teammember.js +++ b/DirectReport/browserview/static/js/teammember.js @@ -1,2 +1,77 @@ + const { useState, useEffect } = React; +const TeamMember = () => { + + const [userData, setUserData] = useState({}); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + fetch(`/account_data`) + .then((response) => { + if (!response.ok) { + throw new Error( + `This is an HTTP error: The status is ${response.status}` + ); + } + return response.json(); + }) + .then((actualData) => { + setUserData(actualData) + setError(null); + }) + .catch((err) => { + setError(err.message); + setUserData(null) + }) + .finally(() => { + setLoading(false); + }); + }, []); + + if (loading) { + return ( +
{`There is a problem fetching the post data - ${error}`}
+ ) + } else { + return ( +
+
+
+

Account: {userData.name}

+

{userData.userid} content

+
+
+
+
+

Account: {userData.userid}

+ + + +
+
+
+
+

Account: {userData.userid}

+

{userData.userid} content

+
+
+
+ +
+
+ ) + } +}; +const domContainer = document.querySelector('#root'); +ReactDOM.render(, domContainer); \ No newline at end of file diff --git a/DirectReport/browserview/static/js/teamreport.js b/DirectReport/browserview/static/js/teamreport.js index e6936fe4..e8f8a0bb 100644 --- a/DirectReport/browserview/static/js/teamreport.js +++ b/DirectReport/browserview/static/js/teamreport.js @@ -5,7 +5,6 @@ const TeamData = () => { const [generatedEmail, setGeneratedEmail] = useState("") const [isOpened, setIsOpened] = useState(false); const [isHidden, setIsHidden] = useState(false); - const [popoverHidden, setPopoverHidden] = useState(false); const handleSubmit = e => { e.preventDefault() @@ -59,9 +58,6 @@ const TeamData = () => { const closePopover = () => { document.getElementById('popover-id-left-purple').classList.toggle("hidden"); - //
-
- diff --git a/DirectReport/browserview/templates/auth/login.html b/DirectReport/browserview/templates/auth/login.html index 8a0bb019..506f98d5 100644 --- a/DirectReport/browserview/templates/auth/login.html +++ b/DirectReport/browserview/templates/auth/login.html @@ -7,6 +7,6 @@ {% block content %}
- +
{% endblock %} \ No newline at end of file diff --git a/DirectReport/browserview/templates/note.html b/DirectReport/browserview/templates/note.html index 5391f99d..1435518c 100644 --- a/DirectReport/browserview/templates/note.html +++ b/DirectReport/browserview/templates/note.html @@ -6,13 +6,7 @@ {% block content %}
-
-
-
-

Notes

-

notes

-
-
-
+
+
{% endblock %} \ No newline at end of file diff --git a/DirectReport/browserview/templates/team.html b/DirectReport/browserview/templates/team.html index d27d2774..0d240222 100644 --- a/DirectReport/browserview/templates/team.html +++ b/DirectReport/browserview/templates/team.html @@ -6,7 +6,7 @@ {% block content %}
-

Team

+
{% endblock %} \ No newline at end of file diff --git a/DirectReport/models/report.py b/DirectReport/models/report.py index 04ea8cc1..97cae176 100644 --- a/DirectReport/models/report.py +++ b/DirectReport/models/report.py @@ -9,7 +9,7 @@ class Report: A class to represent a journal entry. """ - def __init__(self, uuid, summary, created_at): + def __init__(self, uuid, user_id, raw_input, report, created_at): """ Initialize the Entry object. :param uuid: A unique identifier for the entry. @@ -20,7 +20,9 @@ def __init__(self, uuid, summary, created_at): :type created_at: float """ self.uuid = uuid - self.summary = summary + self.user_id = user_id + self.raw_input = raw_input + self.report = report self.created_at = created_at def get_created_at_formatted(self, date_format="%Y-%m-%d %H:%M:%S"): @@ -33,15 +35,15 @@ def get_created_at_formatted(self, date_format="%Y-%m-%d %H:%M:%S"): """ return datetime.datetime.fromtimestamp(self.created_at).strftime(date_format) - def get_modified_on_formatted(self, date_format="%Y-%m-%d %H:%M:%S"): - """ - Get the modified_on timestamp formatted as a string. - :param date_format: The desired format of the timestamp, default is "%Y-%m-%d %H:%M:%S". - :type date_format: str - :return: The formatted modified_on timestamp. - :rtype: str - """ - return datetime.datetime.fromtimestamp(self.modified_on).strftime(date_format) + # def get_modified_on_formatted(self, date_format="%Y-%m-%d %H:%M:%S"): + # """ + # Get the modified_on timestamp formatted as a string. + # :param date_format: The desired format of the timestamp, default is "%Y-%m-%d %H:%M:%S". + # :type date_format: str + # :return: The formatted modified_on timestamp. + # :rtype: str + # """ + # return datetime.datetime.fromtimestamp(self.modified_on).strftime(date_format) def to_dict(self): """ @@ -51,7 +53,9 @@ def to_dict(self): """ return { "uuid": str(self.uuid), - "summary": self.topic, + "user_id": self.user_id, + "raw_input": self.raw_input, + "report": self.report, "created_at": str(self.created_at) } @@ -65,9 +69,11 @@ def from_dict(cls, data): :rtype: Entry """ uuid = data.get("uuid") - summary = data.get("summary") + user_id = data.get("user_id") + raw_input = data.get("raw_input") + report = data.get("report") created_at = datetime.datetime.fromisoformat(data.get("created_at")).timestamp() - return cls(uuid, summary, created_at) + return cls(uuid, user_id, raw_input, report, created_at) # def mark_modified(self): # """ @@ -87,13 +93,13 @@ def is_recent(self, days=7): difference = datetime.datetime.now() - delta return self.created_at >= difference.timestamp() - def set_summary(self, summary): + def set_summary(self, report): """ Update the message of the entry and set the modified_on timestamp to the current time. :param new_message: The new message/content for the entry. :type new_message: str """ - self.summary = summary + self.report = report def __iter__(self): return self @@ -105,4 +111,4 @@ def __repr__(self): return self.__str__() def __len__(self): - return len(self.summary) + return len(self.report) diff --git a/DirectReport/models/report_builder.py b/DirectReport/models/report_builder.py new file mode 100644 index 00000000..e9a1a4b8 --- /dev/null +++ b/DirectReport/models/report_builder.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 + +import datetime +import uuid +from DirectReport.models.report import Report +from DirectReport.models.report_model import ReportModel + +class ReportBuilder: + + """ + A class to facilitate creating, deleting and listing entries in a weekly and daily report system. + """ + + def __init__(self): + pass + + @staticmethod + def new(report, raw_input, user_id): + """ + Creates a new entry with the given entry text and topic. + :param entry_text: The entry text. + :param topic_text: The topic for the entry (optional). + """ + today = datetime.date.today().strftime("%m/%d/%Y") + storage = ReportModel('ReportStorage.db') + storage.create_table() + if report is None or report == '': + report = "Entry for work on " + str(today) + new_report = Report( + str(uuid.uuid1()), user_id, raw_input, report, datetime.datetime.now().timestamp() + ) + storage.add_report(new_report) + + # @staticmethod + # def update(uid, summary_text, created_at): + # """ + # Updates an entry with the given entry text and topic. + # :param uid: The entry id. + # :param entry_text: The entry text. + # :param topic_text: The topic for the entry + # :param created_at: The date entry was created. + # :param weekly_id: The weekly id. + # """ + # storage = ReportModel('EntryStorage.db') + # storage.create_table() + # new_entry = Report( + # str(uuid.UUID(uid)), summary_text, created_at, datetime.datetime.now().timestamp() + # ) + # storage(new_entry) + + @staticmethod + def delete(entry_id): + """ + Deletes an entry with the specified ID. + :param entry_id: The ID of the entry to delete. + """ + storage = ReportModel('ReportStorage.db') + storage.delete_entry(entry_id) + + @staticmethod + def get_reports_for_user_id(user_id): + """ + Deletes an entry with the specified ID. + :param entry_id: The ID of the entry to delete. + """ + storage = ReportModel('ReportStorage.db') + user_reports = storage.get_report(user_id) + return user_reports + + @staticmethod + def list_today(): + """ + Lists all entries for today. + :return: A list of entries for today. + """ + storage = ReportModel('ReportStorage.db') + list = storage.list_all_reports() + return list + + @staticmethod + def list_all(): + """ + Lists all entries. + :return: A list of all entries. + """ + storage = ReportModel('ReportStorage.db') + list_items = storage.list_all_reports_as_dict() + return list_items \ No newline at end of file diff --git a/DirectReport/models/report_model.py b/DirectReport/models/report_model.py index d3ebc6b1..9383cfc2 100644 --- a/DirectReport/models/report_model.py +++ b/DirectReport/models/report_model.py @@ -21,28 +21,30 @@ def create_table(self): """ Creates the `entries` table in the SQLite database if it doesn't exist. """ - query = "CREATE TABLE IF NOT EXISTS reports (uuid TEXT PRIMARY KEY, summary TEXT,created_at TEXT)" + query = "CREATE TABLE IF NOT EXISTS reports (uuid TEXT PRIMARY KEY, user_id TEXT, raw_input TEXT, report TEXT, created_at TEXT)" self.conn.execute(query) self.conn.commit() - def add_report(self, entry): + def add_report(self, report): """ Adds an `Entry` object to the SQLite database. :param entry: The `Entry` object to add. """ values = ( - entry.uuid.__str__(), - entry.summary, - entry.created_at.__str__() + report.uuid.__str__(), + report.user_id.__str__(), + report.raw_input.__str__(), + report.report.__str__(), + report.created_at.__str__() ) self.conn.execute( - "INSERT OR IGNORE INTO reports (uuid, summary, created_at) VALUES (?, ?, ?)", + "INSERT OR IGNORE INTO reports (uuid, user_id, raw_input, report, created_at) VALUES (?, ?, ?, ?, ?)", values, ) self.conn.commit() - def get_report(self, uuid): + def get_report(self, user_id): """ Retrieves an `Entry` object from the SQLite database by its UUID. :param uuid: The UUID of the entry to retrieve. @@ -50,8 +52,8 @@ def get_report(self, uuid): """ result = self.conn.execute( - "SELECT uuid, summary, created_at FROM reports WHERE uuid = ?", - (str(uuid),), + "SELECT uuid, user_id, raw_input, report, created_at FROM reports WHERE user_id = ?", + (str(user_id),), ) row = result.fetchone() if row: @@ -86,7 +88,7 @@ def get_uuid(self, date): """ result = self.conn.execute( - "SELECT uuid, summary, created_at FROM reports WHERE modified_on = ?", + "SELECT uuid, user_id, raw_input, report, created_at FROM reports WHERE modified_on = ?", (str(date),), ) if result is not None: @@ -118,7 +120,7 @@ def list_all_reports_as_dict(self): results_list = [] for result in results: - entry = Entry(*result) + entry = Report(*result) entry_dict = entry.to_dict() results_list.append(entry_dict) return results_list diff --git a/DirectReport/models/user_model.py b/DirectReport/models/user_model.py index 6d939fc1..c0228fb5 100644 --- a/DirectReport/models/user_model.py +++ b/DirectReport/models/user_model.py @@ -37,6 +37,7 @@ def create_table(self): cursor.execute(""" CREATE TABLE IF NOT EXISTS users ( id TEXT NOT NULL, + uid TEXT NOT NULL, username TEXT NOT NULL, email TEXT UNIQUE NOT NULL PRIMARY KEY, password TEXT NOT NULL @@ -44,11 +45,11 @@ def create_table(self): """) self.conn.commit() - def insert_user(self, username, email, password): + def insert_user(self, id, username, email, password): cursor = self.conn.cursor() uuid_str = str(uuid.uuid4()) try: - cursor.execute("INSERT INTO users (id, username, email, password) VALUES (?, ?, ?, ?)", (uuid_str, username, email, password)) + cursor.execute("INSERT INTO users (id, uid, username, email, password) VALUES (?, ?, ?, ?, ?)", (id, uuid_str, username, email, password)) self.conn.commit() print("User added successfully!") except sqlite3.IntegrityError: @@ -56,15 +57,16 @@ def insert_user(self, username, email, password): def get_user_by_email(self, email): cursor = self.conn.cursor() - cursor.execute("SELECT id, username, email, password FROM users WHERE email=?", (email,)) + cursor.execute("SELECT id, uid, username, email, password FROM users WHERE email=?", (email,)) result = cursor.fetchone() if result: - return User(result[0], result[1], result[2], result[3]) + return User(result[0], result[2], result[3], result[4]) + # User(result[0], result[2], result[3], result[4]) return None def get_all_users(self): cursor = self.conn.cursor() - cursor.execute("SELECT id, username, email FROM users") + cursor.execute("SELECT id, uid, username, email FROM users") return cursor.fetchall() def close(self): From 32ed66276fbde4a871bb84e7fb96d42deb7acc28 Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Sun, 10 Dec 2023 17:30:01 -0500 Subject: [PATCH 11/21] cleanup codebase, remove commented code --- DirectReport/browserview/auth/auth.py | 41 +--------------------- DirectReport/browserview/static/js/list.js | 3 -- DirectReport/models/report_builder.py | 17 --------- DirectReport/models/report_model.py | 10 ------ DirectReport/models/user_model.py | 1 - 5 files changed, 1 insertion(+), 71 deletions(-) diff --git a/DirectReport/browserview/auth/auth.py b/DirectReport/browserview/auth/auth.py index d9d476eb..77fdb435 100644 --- a/DirectReport/browserview/auth/auth.py +++ b/DirectReport/browserview/auth/auth.py @@ -1,42 +1,3 @@ from flask import Blueprint -from flask import Flask, render_template, request, redirect, json, url_for -from werkzeug.security import generate_password_hash -from DirectReport.models.user_model import UserModel -from DirectReport.models.list_builder import ListBuilder -from DirectReport.browserview.prompt_logic import generate_email -from DirectReport.browserview.github import GithubClient -from flask_login import LoginManager, login_user, login_required, logout_user, current_user -from DirectReport.datadependencies import appsecrets -# from .auth.auth import auth -auth = Blueprint('auth', __name__) - -# @auth.route('/signup') -# def signup(): -# pass -# -# @auth.route('/login') -# def login(): -# pass -# -# @auth.route('/logout') -# def logout(): -# pass - - - -# from flask import Blueprint -# -# auth = Blueprint('auth', __name__) -# -# @auth.route('/login') -# def login(): -# return 'Login' -# -# @auth.route('/signup') -# def signup(): -# return 'Signup' -# -# @auth.route('/logout') -# def logout(): -# return 'Logout' \ No newline at end of file +auth = Blueprint('auth', __name__) \ No newline at end of file diff --git a/DirectReport/browserview/static/js/list.js b/DirectReport/browserview/static/js/list.js index ac72edbf..4af6316e 100644 --- a/DirectReport/browserview/static/js/list.js +++ b/DirectReport/browserview/static/js/list.js @@ -21,9 +21,6 @@ class EntryList extends React.Component { } } - - - class EmptyEntryList extends React.Component { render() { return ( diff --git a/DirectReport/models/report_builder.py b/DirectReport/models/report_builder.py index e9a1a4b8..5d8d9793 100644 --- a/DirectReport/models/report_builder.py +++ b/DirectReport/models/report_builder.py @@ -31,23 +31,6 @@ def new(report, raw_input, user_id): ) storage.add_report(new_report) - # @staticmethod - # def update(uid, summary_text, created_at): - # """ - # Updates an entry with the given entry text and topic. - # :param uid: The entry id. - # :param entry_text: The entry text. - # :param topic_text: The topic for the entry - # :param created_at: The date entry was created. - # :param weekly_id: The weekly id. - # """ - # storage = ReportModel('EntryStorage.db') - # storage.create_table() - # new_entry = Report( - # str(uuid.UUID(uid)), summary_text, created_at, datetime.datetime.now().timestamp() - # ) - # storage(new_entry) - @staticmethod def delete(entry_id): """ diff --git a/DirectReport/models/report_model.py b/DirectReport/models/report_model.py index 9383cfc2..8554d2d4 100644 --- a/DirectReport/models/report_model.py +++ b/DirectReport/models/report_model.py @@ -61,16 +61,6 @@ def get_report(self, user_id): else: return None - # def update_entry(self, entry): - # """ - # Updates an existing `Entry` object in the SQLite database. - # :param entry: The `Entry` object to update. - # """ - # - # values = (entry.message, entry.modified_on, str(entry.uuid)) - # self.conn.execute("UPDATE entries SET message = ?, modified_on = ? WHERE uuid = ?", values) - # self.conn.commit() - def delete_entry(self, uuid): """ Deletes an `Entry` object from the SQLite database by its UUID. diff --git a/DirectReport/models/user_model.py b/DirectReport/models/user_model.py index c0228fb5..b9cf57bd 100644 --- a/DirectReport/models/user_model.py +++ b/DirectReport/models/user_model.py @@ -61,7 +61,6 @@ def get_user_by_email(self, email): result = cursor.fetchone() if result: return User(result[0], result[2], result[3], result[4]) - # User(result[0], result[2], result[3], result[4]) return None def get_all_users(self): From aac937065cabaa1179b9aad7c80251f096c7561d Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Sun, 10 Dec 2023 18:11:19 -0500 Subject: [PATCH 12/21] update user model --- DirectReport/browserview/app.py | 43 ++++++++----------- DirectReport/browserview/static/css/main.css | 31 ------------- DirectReport/browserview/static/js/account.js | 2 +- DirectReport/browserview/static/js/signup.js | 17 ++++++-- DirectReport/browserview/templates/base.html | 2 +- DirectReport/models/list_builder.py | 1 + DirectReport/models/report.py | 16 ------- DirectReport/models/report_builder.py | 1 + DirectReport/models/report_model.py | 3 ++ DirectReport/models/team.py | 3 ++ DirectReport/models/team_member.py | 3 ++ DirectReport/models/team_member_model.py | 3 ++ DirectReport/models/team_model.py | 3 ++ DirectReport/models/user_model.py | 21 ++++++--- 14 files changed, 64 insertions(+), 85 deletions(-) diff --git a/DirectReport/browserview/app.py b/DirectReport/browserview/app.py index ee686989..6fe216fc 100644 --- a/DirectReport/browserview/app.py +++ b/DirectReport/browserview/app.py @@ -46,12 +46,14 @@ def signup(): if request.method == 'POST': # code to validate and add user to database goes here email = request.form.get('email') - name = request.form.get('name') username = request.form.get('username') + firstname= request.form.get('firstname') + lastname = request.form.get('lastname') passwordtext = request.form.get('password') password = generate_password_hash(passwordtext) - user_model.insert_user(username, name, email, password) - # insert_user(name, email, password)) + user_model = UserModel() + user_model.insert_user(email, username, firstname, lastname, email, password) + # insert_user(username, firstname, lastname, email, password)) return redirect(url_for('login')) return render_template('auth/signup.html') @@ -76,10 +78,6 @@ def logout(): @login_manager.user_loader def user_loader(email): user = user_model.get_user_by_email(email) - users = user_model.get_all_users() - print("user loader") - print(user) - print(users) return user @login_manager.request_loader @@ -96,11 +94,17 @@ def account(): @app.route("/account_data", methods=['GET']) @login_required def account_data(): - entries_list = { - "name": current_user.username, - "userid": current_user.id + user_account = { + "name": current_user.firstname + " " + current_user.lastname, + "first_name": current_user.firstname, + "last_name": current_user.lastname, + "userid": current_user.id, + "email": current_user.email, + "username": current_user.username, + "firstname": current_user.firstname, + "lastname": current_user.lastname } - return entries_list, 201 + return user_account, 201 @app.route("/list", methods=['GET', 'POST']) @@ -170,12 +174,6 @@ def team_report(): def team(): return render_template('team.html', title='Team', data=[]) -# @app.route("/team/", methods=['GET', 'POST']) -# def team_report(): -# if request.method == "POST": -# print("POST") -# return render_template('team_member.html', title='Team Member', data=[]) - @app.route("/report", methods=['GET', 'POST']) @login_required def report(): @@ -183,16 +181,9 @@ def report(): prompt = request.get_json()["prompt"] elements = TEST_DATA_ELEMENTS client = GithubClient() - # elements["shortlog"] = client.parse_git_shortlog(logitem) - # ReportBuilder.new(elements["report"], prompt, current_user.id) + logitem = "Adrian Prantl (67):\n add mangling testcase\n Debug Info: Represent private discriminators in DWARF.\n Revert \"Debug Info: Represent private discriminators in DWARF.\"\n Debug Info: Represent private discriminators in DWARF.\n Un-XFAIL and update test.\n Move the logic for ignoring the debug locations for closure setup code into SILGen. NFC-ish.\n Debug Info: Associate a function call with the beginning of the expression.\n Debug Info / SILGen: fix the source location of variable assignments\n typo\n Fix the debug locations of inserted operations in AvailableValueAggregator.\n Don't emit shadow copies for anonymous variables.\n Remove dead API IRGenDebugInfo::setArtificialTrapLocation().\n Use compiler-generated location for func.-sig.-spec. thunks\n whitespace\n Fix the missing inlined-at field of function-level SILDebugScopes.\n Add debug info support for inlined and specialized generic variables.\n Revert \"Add debug info support for inlined and specialized generic variables.\"\n Add debug info support for inlined and specialized generic variables.\n Update mangling prefix in Mangling.rst\n Add initial support for debug info for coroutine allocas.\n Temporarily disable failing test case, rdar://problem/43340064\n Add build-script support for the Swift LLDB backwards-compatibility tests.\n Remove accidentally committed debugging code\n Deserialize Swift compatibility version in CompilerInvocation::loadFromSerializedAST()\n SILGen: Preserve function argument debug info for arguments needing alloc_stack\n Use as the filename for SILLocation-less functions to avoid misleading source locatio\nns in backtraces.\n Add a -verify-linetable LLVM option.\n Enable debug info for inlined generics by default. It works now.\n Fix nonasserts compilation\n\nAhmad Alhashemi (5):\n [Parser] Detect nonbreaking space U+00A0 and fixit\n Move non-breaking space handling to lexUnknown\n Add more non-breaking space test cases\n Minor style edits\n Add tests for non-breaking space detect and fix-it\n\nAkshay Shrimali (1):\n Update README.md\n\nAlan Zeino (1):\n Fix typo in code example in libSyntax README\n\nAlbin \"albinek\" Sadowski (1):\n Fix syntax highlighting in CHANGELOG (#15107)\n\nAlejandro (3):\n Remove a warning, some doc fixes (#16863)\n [SR-8178] Fix BinaryFloatingPoint.random(in:) open range returning upperBound (#17794)\n [Docs] Fix minor code typo in SILPro..Man..md\n\nAlex Blewitt (5):\n [SR-7032] Fix compare for lhs and rhs\n [SR-7036] Use || instead of && for kind comparison\n [SR-7041] Remove duplicate conditional check\n Remove duplicate verb\n [SR-7043] Remove duplicate if statement" + elements["shortlog"] = client.parse_git_shortlog(logitem) print(ReportBuilder.get_reports_for_user_id(current_user.id)) - # if request.method == "POST": - # - # - # # builder = ReportBuilder() - # ReportBuilder.new(elements["report"]) - # list = ReportBuilder.list_all() - # print(list) return elements, 201 @app.route("/generate_email", methods=['POST']) diff --git a/DirectReport/browserview/static/css/main.css b/DirectReport/browserview/static/css/main.css index cd0ea455..e69de29b 100644 --- a/DirectReport/browserview/static/css/main.css +++ b/DirectReport/browserview/static/css/main.css @@ -1,31 +0,0 @@ -/* temp */ - -/*.text-center {*/ -/* text-align: center;*/ -/*}*/ -/*.font-weight-400 {*/ -/* font-weight: 400;*/ -/*}*/ - -/*@import "tailwindcss/base";*/ - -/*@import "tailwindcss/components";*/ - - -/*@import "tailwindcss/utilities";*/ - -/*@media (min-width:320px) {*/ -/* .container {*/ -/* !* Mobile by default as Roy pointed out *!*/ -/* display: flex;*/ -/* flex-direction: column;*/ -/* }*/ -/*}*/ - - -/*@media (min-width: 768px) {*/ -/* !* For desktops *!*/ -/* .container {*/ -/* flex-direction: row;*/ -/* }*/ -/*}*/ \ No newline at end of file diff --git a/DirectReport/browserview/static/js/account.js b/DirectReport/browserview/static/js/account.js index cdd2160e..b0f5e47b 100644 --- a/DirectReport/browserview/static/js/account.js +++ b/DirectReport/browserview/static/js/account.js @@ -39,7 +39,7 @@ const Account = () => {

Account: {userData.name}

-

{userData.userid} content

+

{userData.username}

diff --git a/DirectReport/browserview/static/js/signup.js b/DirectReport/browserview/static/js/signup.js index 4a2032fc..f94f3c4c 100644 --- a/DirectReport/browserview/static/js/signup.js +++ b/DirectReport/browserview/static/js/signup.js @@ -20,18 +20,27 @@ const SignupForm = () => { placeholder="name@company.com" required=""/>
- - +
+
+ +
{% block style %}{% endblock %} -{# #} +
{% include "_navigation.html" %} diff --git a/DirectReport/models/list_builder.py b/DirectReport/models/list_builder.py index cd4959ea..8422dfb3 100644 --- a/DirectReport/models/list_builder.py +++ b/DirectReport/models/list_builder.py @@ -4,6 +4,7 @@ import uuid from DirectReport.models.entry import Entry from DirectReport.models.entry_storage import EntryStorage + class ListBuilder: """ diff --git a/DirectReport/models/report.py b/DirectReport/models/report.py index 97cae176..2a3a456e 100644 --- a/DirectReport/models/report.py +++ b/DirectReport/models/report.py @@ -35,16 +35,6 @@ def get_created_at_formatted(self, date_format="%Y-%m-%d %H:%M:%S"): """ return datetime.datetime.fromtimestamp(self.created_at).strftime(date_format) - # def get_modified_on_formatted(self, date_format="%Y-%m-%d %H:%M:%S"): - # """ - # Get the modified_on timestamp formatted as a string. - # :param date_format: The desired format of the timestamp, default is "%Y-%m-%d %H:%M:%S". - # :type date_format: str - # :return: The formatted modified_on timestamp. - # :rtype: str - # """ - # return datetime.datetime.fromtimestamp(self.modified_on).strftime(date_format) - def to_dict(self): """ Convert the Entry object to a dictionary. @@ -75,12 +65,6 @@ def from_dict(cls, data): created_at = datetime.datetime.fromisoformat(data.get("created_at")).timestamp() return cls(uuid, user_id, raw_input, report, created_at) - # def mark_modified(self): - # """ - # Update the modified_on timestamp to the current time. - # """ - # self.modified_on = datetime.datetime.now().strftime("%m/%d/%Y") - def is_recent(self, days=7): """ Check if the entry is recent (created within the specified number of days). diff --git a/DirectReport/models/report_builder.py b/DirectReport/models/report_builder.py index 5d8d9793..e08c60ab 100644 --- a/DirectReport/models/report_builder.py +++ b/DirectReport/models/report_builder.py @@ -5,6 +5,7 @@ from DirectReport.models.report import Report from DirectReport.models.report_model import ReportModel + class ReportBuilder: """ diff --git a/DirectReport/models/report_model.py b/DirectReport/models/report_model.py index 8554d2d4..cea02719 100644 --- a/DirectReport/models/report_model.py +++ b/DirectReport/models/report_model.py @@ -1,6 +1,9 @@ +#!/usr/bin/env python3 + import sqlite3 from DirectReport.models.report import Report + class ReportModel: """ A class to interact with SQLite database for storing and retrieving `Entry` objects. diff --git a/DirectReport/models/team.py b/DirectReport/models/team.py index 7214cbc1..fae4d30b 100644 --- a/DirectReport/models/team.py +++ b/DirectReport/models/team.py @@ -1,6 +1,9 @@ +#!/usr/bin/env python3 + import sqlite3 import uuid + class Team: def __init__(self, team_id, team_name, team_email): diff --git a/DirectReport/models/team_member.py b/DirectReport/models/team_member.py index dbaae043..131d89ef 100644 --- a/DirectReport/models/team_member.py +++ b/DirectReport/models/team_member.py @@ -1,6 +1,9 @@ +#!/usr/bin/env python3 + import sqlite3 import uuid + class TeamMember: def __init__(self, id, team_id, username): diff --git a/DirectReport/models/team_member_model.py b/DirectReport/models/team_member_model.py index edd72f4e..3cf5d5a2 100644 --- a/DirectReport/models/team_member_model.py +++ b/DirectReport/models/team_member_model.py @@ -1,6 +1,9 @@ +#!/usr/bin/env python3 + import sqlite3 import uuid + class TeamMemberModel: def __init__(self, db_name="teammember.db"): diff --git a/DirectReport/models/team_model.py b/DirectReport/models/team_model.py index 3e0410ba..f0b6696d 100644 --- a/DirectReport/models/team_model.py +++ b/DirectReport/models/team_model.py @@ -1,6 +1,9 @@ +#!/usr/bin/env python3 + import sqlite3 import uuid + class TeamModel: def __init__(self, db_name="team.db"): diff --git a/DirectReport/models/user_model.py b/DirectReport/models/user_model.py index b9cf57bd..3a8e2977 100644 --- a/DirectReport/models/user_model.py +++ b/DirectReport/models/user_model.py @@ -1,13 +1,18 @@ +#!/usr/bin/env python3 + import sqlite3 import uuid from flask_login import UserMixin # from app import app as application + class User(UserMixin): - def __init__(self, id, username, email, password): + def __init__(self, id, username, firstname, lastname, email, password): self.id = email self.uid = id self.username = username + self.firstname = firstname + self.lastname = lastname self.email = email self.password = password self.authenticated = True @@ -27,6 +32,7 @@ def is_active(self): def get_id(self): return self.id + class UserModel: def __init__(self, db_name="users.db"): self.conn = sqlite3.connect(db_name, check_same_thread=False) @@ -39,17 +45,19 @@ def create_table(self): id TEXT NOT NULL, uid TEXT NOT NULL, username TEXT NOT NULL, + firstname TEXT NOT NULL, + lastname TEXT NOT NULL, email TEXT UNIQUE NOT NULL PRIMARY KEY, password TEXT NOT NULL ) """) self.conn.commit() - def insert_user(self, id, username, email, password): + def insert_user(self, id, username, firstname, lastname, email, password): cursor = self.conn.cursor() uuid_str = str(uuid.uuid4()) try: - cursor.execute("INSERT INTO users (id, uid, username, email, password) VALUES (?, ?, ?, ?, ?)", (id, uuid_str, username, email, password)) + cursor.execute("INSERT INTO users (id, uid, username, firstname, lastname, email, password) VALUES (?, ?, ?, ?, ?, ?, ?)", (id, uuid_str, username, firstname, lastname, email, password)) self.conn.commit() print("User added successfully!") except sqlite3.IntegrityError: @@ -57,15 +65,16 @@ def insert_user(self, id, username, email, password): def get_user_by_email(self, email): cursor = self.conn.cursor() - cursor.execute("SELECT id, uid, username, email, password FROM users WHERE email=?", (email,)) + cursor.execute("SELECT id, uid, username, firstname, lastname, email, password FROM users WHERE email=?", (email,)) result = cursor.fetchone() if result: - return User(result[0], result[2], result[3], result[4]) + return User(result[0], result[2], result[3], result[4], result[5], result[6]) + # User(result[0], result[2], result[3], result[4])) return None def get_all_users(self): cursor = self.conn.cursor() - cursor.execute("SELECT id, uid, username, email FROM users") + cursor.execute("SELECT id, uid, username, firstname, lastname, email FROM users") return cursor.fetchall() def close(self): From 01f119343e266350c541218cfa6ce461ad8758dd Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Sun, 10 Dec 2023 19:44:24 -0500 Subject: [PATCH 13/21] update for report screen --- DirectReport/browserview/app.py | 63 ++-- DirectReport/browserview/modelclient.py | 6 +- DirectReport/browserview/static/js/account.js | 9 +- DirectReport/browserview/static/js/list.js | 6 +- DirectReport/browserview/static/js/note.js | 318 +++++++++++------- .../browserview/templates/detail.html | 5 +- DirectReport/models/report_builder.py | 2 +- DirectReport/models/report_model.py | 24 ++ 8 files changed, 277 insertions(+), 156 deletions(-) diff --git a/DirectReport/browserview/app.py b/DirectReport/browserview/app.py index 6fe216fc..fd1fe44b 100644 --- a/DirectReport/browserview/app.py +++ b/DirectReport/browserview/app.py @@ -14,6 +14,7 @@ from DirectReport.datadependencies import appsecrets from .auth.auth import auth from .modelclient import TEST_DATA_ELEMENTS +from .modelclient import RAW_REPORT_DATA login_manager = LoginManager() app = Flask(__name__, template_folder="templates") @@ -53,7 +54,6 @@ def signup(): password = generate_password_hash(passwordtext) user_model = UserModel() user_model.insert_user(email, username, firstname, lastname, email, password) - # insert_user(username, firstname, lastname, email, password)) return redirect(url_for('login')) return render_template('auth/signup.html') @@ -62,9 +62,9 @@ def login(): if request.method == 'POST': email = request.form.get('email') password = request.form.get('password') - # remember = True if request.form.get('remember') else False + remember = True if request.form.get('remember') else False user = user_loader(email) - login_user(user, remember=True, force=True) + login_user(user, remember=remember, force=True) if current_user.is_authenticated(): return redirect(url_for('account')) return render_template('auth/login.html') @@ -94,17 +94,27 @@ def account(): @app.route("/account_data", methods=['GET']) @login_required def account_data(): + saved_reports = ReportBuilder.get_reports_for_user_id(current_user.id) + report_results = [] + for report in saved_reports: + report_element = { + "report": report + } + report_results.append(report_element) + user_account = { "name": current_user.firstname + " " + current_user.lastname, - "first_name": current_user.firstname, - "last_name": current_user.lastname, + "firstname": current_user.firstname, + "lastname": current_user.lastname, "userid": current_user.id, - "email": current_user.email, "username": current_user.username, - "firstname": current_user.firstname, - "lastname": current_user.lastname + "email": current_user.email } - return user_account, 201 + user_element = { + "user": user_account, + "reports": report_results + } + return user_element, 201 @app.route("/list", methods=['GET', 'POST']) @@ -114,14 +124,20 @@ def list_entries(): Retrieves and renders the list of all entries. :return: Rendered HTML template for the list page. """ - entries_list = ListBuilder.list_all() - return render_template('list.html', title='List', data=entries_list) + reports = ReportBuilder.get_reports_for_user_id(current_user.id) + report_results = [] + for report in reports: + report_element = { + "report": report + } + report_results.append(report_element) + return render_template('list.html', title='List', data=report_results) @app.route("/getlist", methods=['GET']) @login_required def get_list(): - entries_list = ListBuilder.list_all() - return entries_list, 201 + reports = ReportBuilder.get_reports_for_user_id(current_user.id) + return reports, 201 @app.route('/entry/', methods=['GET', 'POST']) @login_required @@ -132,14 +148,17 @@ def detail(uid=None): :param uid: The ID of the entry to display. :return: Rendered HTML template for the entry details page. """ - item = EntryStorage('SQLite_Python.db') - if request.method == "POST": - json_data = request.get_json() - ListBuilder.update( - json_data["id"], json_data['entry'], json_data['topic'], json_data['created_at'], json_data['week_id'] - ) - entry = item.get_entry(uid).to_dict() - return render_template('detail.html', title='Detail', data=entry) + reports = ReportBuilder.get_reports_for_user_id(current_user.id) + report = filter(lambda report: report["uuid"] == uid, reports) + # report = {} + # item = EntryStorage('SQLite_Python.db') + # if request.method == "POST": + # json_data = request.get_json() + # ListBuilder.update( + # json_data["id"], json_data['entry'], json_data['topic'], json_data['created_at'], json_data['week_id'] + # ) + # entry = item.get_entry(uid).to_dict() + return render_template('detail.html', title='Detail', data=report) @app.route("/new", methods=['GET', 'POST']) @login_required @@ -183,7 +202,7 @@ def report(): client = GithubClient() logitem = "Adrian Prantl (67):\n add mangling testcase\n Debug Info: Represent private discriminators in DWARF.\n Revert \"Debug Info: Represent private discriminators in DWARF.\"\n Debug Info: Represent private discriminators in DWARF.\n Un-XFAIL and update test.\n Move the logic for ignoring the debug locations for closure setup code into SILGen. NFC-ish.\n Debug Info: Associate a function call with the beginning of the expression.\n Debug Info / SILGen: fix the source location of variable assignments\n typo\n Fix the debug locations of inserted operations in AvailableValueAggregator.\n Don't emit shadow copies for anonymous variables.\n Remove dead API IRGenDebugInfo::setArtificialTrapLocation().\n Use compiler-generated location for func.-sig.-spec. thunks\n whitespace\n Fix the missing inlined-at field of function-level SILDebugScopes.\n Add debug info support for inlined and specialized generic variables.\n Revert \"Add debug info support for inlined and specialized generic variables.\"\n Add debug info support for inlined and specialized generic variables.\n Update mangling prefix in Mangling.rst\n Add initial support for debug info for coroutine allocas.\n Temporarily disable failing test case, rdar://problem/43340064\n Add build-script support for the Swift LLDB backwards-compatibility tests.\n Remove accidentally committed debugging code\n Deserialize Swift compatibility version in CompilerInvocation::loadFromSerializedAST()\n SILGen: Preserve function argument debug info for arguments needing alloc_stack\n Use as the filename for SILLocation-less functions to avoid misleading source locatio\nns in backtraces.\n Add a -verify-linetable LLVM option.\n Enable debug info for inlined generics by default. It works now.\n Fix nonasserts compilation\n\nAhmad Alhashemi (5):\n [Parser] Detect nonbreaking space U+00A0 and fixit\n Move non-breaking space handling to lexUnknown\n Add more non-breaking space test cases\n Minor style edits\n Add tests for non-breaking space detect and fix-it\n\nAkshay Shrimali (1):\n Update README.md\n\nAlan Zeino (1):\n Fix typo in code example in libSyntax README\n\nAlbin \"albinek\" Sadowski (1):\n Fix syntax highlighting in CHANGELOG (#15107)\n\nAlejandro (3):\n Remove a warning, some doc fixes (#16863)\n [SR-8178] Fix BinaryFloatingPoint.random(in:) open range returning upperBound (#17794)\n [Docs] Fix minor code typo in SILPro..Man..md\n\nAlex Blewitt (5):\n [SR-7032] Fix compare for lhs and rhs\n [SR-7036] Use || instead of && for kind comparison\n [SR-7041] Remove duplicate conditional check\n Remove duplicate verb\n [SR-7043] Remove duplicate if statement" elements["shortlog"] = client.parse_git_shortlog(logitem) - print(ReportBuilder.get_reports_for_user_id(current_user.id)) + ReportBuilder.new(elements, RAW_REPORT_DATA, current_user.id) return elements, 201 @app.route("/generate_email", methods=['POST']) diff --git a/DirectReport/browserview/modelclient.py b/DirectReport/browserview/modelclient.py index a996835e..16864df4 100644 --- a/DirectReport/browserview/modelclient.py +++ b/DirectReport/browserview/modelclient.py @@ -1,4 +1,7 @@ global TEST_DATA_ELEMENTS +global RAW_REPORT_DATA + +RAW_REPORT_DATA = "Adrian Prantl (67):\n add mangling testcase\n Debug Info: Represent private discriminators in DWARF.\n Revert \"Debug Info: Represent private discriminators in DWARF.\"\n Debug Info: Represent private discriminators in DWARF.\n Un-XFAIL and update test.\n Move the logic for ignoring the debug locations for closure setup code into SILGen. NFC-ish.\n Debug Info: Associate a function call with the beginning of the expression.\n Debug Info / SILGen: fix the source location of variable assignments\n typo\n Fix the debug locations of inserted operations in AvailableValueAggregator.\n Don't emit shadow copies for anonymous variables.\n Remove dead API IRGenDebugInfo::setArtificialTrapLocation().\n Use compiler-generated location for func.-sig.-spec. thunks\n whitespace\n Fix the missing inlined-at field of function-level SILDebugScopes.\n Add debug info support for inlined and specialized generic variables.\n Revert \"Add debug info support for inlined and specialized generic variables.\"\n Add debug info support for inlined and specialized generic variables.\n Update mangling prefix in Mangling.rst\n Add initial support for debug info for coroutine allocas.\n Temporarily disable failing test case, rdar://problem/43340064\n Add build-script support for the Swift LLDB backwards-compatibility tests.\n Remove accidentally committed debugging code\n Deserialize Swift compatibility version in CompilerInvocation::loadFromSerializedAST()\n SILGen: Preserve function argument debug info for arguments needing alloc_stack\n Use as the filename for SILLocation-less functions to avoid misleading source locatio\nns in backtraces.\n Add a -verify-linetable LLVM option.\n Enable debug info for inlined generics by default. It works now.\n Fix nonasserts compilation\n\nAhmad Alhashemi (5):\n [Parser] Detect nonbreaking space U+00A0 and fixit\n Move non-breaking space handling to lexUnknown\n Add more non-breaking space test cases\n Minor style edits\n Add tests for non-breaking space detect and fix-it\n\nAkshay Shrimali (1):\n Update README.md\n\nAlan Zeino (1):\n Fix typo in code example in libSyntax README\n\nAlbin \"albinek\" Sadowski (1):\n Fix syntax highlighting in CHANGELOG (#15107)\n\nAlejandro (3):\n Remove a warning, some doc fixes (#16863)\n [SR-8178] Fix BinaryFloatingPoint.random(in:) open range returning upperBound (#17794)\n [Docs] Fix minor code typo in SILPro..Man..md\n\nAlex Blewitt (5):\n [SR-7032] Fix compare for lhs and rhs\n [SR-7036] Use || instead of && for kind comparison\n [SR-7041] Remove duplicate conditional check\n Remove duplicate verb\n [SR-7043] Remove duplicate if statement" TEST_DATA_ELEMENTS = elements = { "team": [ @@ -58,4 +61,5 @@ ], "conclusion": "The team demonstrated good progress this week, with a focus on enhancing DebugInfo and SILGen, improving the Parser, and implementing various fixes. The team should continue to focus on these areas in the coming week." } - } \ No newline at end of file + } + diff --git a/DirectReport/browserview/static/js/account.js b/DirectReport/browserview/static/js/account.js index b0f5e47b..ffa765b2 100644 --- a/DirectReport/browserview/static/js/account.js +++ b/DirectReport/browserview/static/js/account.js @@ -3,6 +3,7 @@ const { useState, useEffect } = React; const Account = () => { const [userData, setUserData] = useState({}); + const [reportData, setReportData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -17,12 +18,14 @@ const Account = () => { return response.json(); }) .then((actualData) => { - setUserData(actualData) + setUserData(actualData["user"]); + setReportData(actualData["reports"]); setError(null); }) .catch((err) => { setError(err.message); setUserData(null) + setReportData(null) }) .finally(() => { setLoading(false); @@ -40,6 +43,10 @@ const Account = () => {

Account: {userData.name}

{userData.username}

+

Number of reports saved: {reportData.length}

+ {/*{reportData && reportData.map(hightlight =>*/} + {/*

{hightlight.report.raw_input}

*/} + {/*)}*/}
diff --git a/DirectReport/browserview/static/js/list.js b/DirectReport/browserview/static/js/list.js index 4af6316e..3c2dec78 100644 --- a/DirectReport/browserview/static/js/list.js +++ b/DirectReport/browserview/static/js/list.js @@ -9,8 +9,8 @@ class EntryList extends React.Component { @@ -51,7 +51,7 @@ const App = () => { return response.json(); }) .then((actualData) => { - setListData(actualData) + setListData(actualData); setError(null); }) .catch((err) => { diff --git a/DirectReport/browserview/static/js/note.js b/DirectReport/browserview/static/js/note.js index ccf95530..0f5c89a8 100644 --- a/DirectReport/browserview/static/js/note.js +++ b/DirectReport/browserview/static/js/note.js @@ -1,140 +1,204 @@ 'use strict'; const elem = React.createElement; +const { useState, useEffect } = React; const rootElement = document.getElementById('root') -const dateItem = new Date(data.created_at).toLocaleDateString() - -class Entry extends React.Component { - - constructor(props) { - super(props); - - this.state = { - isEditting: false, - topic: '', - entry: '', - modified_on: '' - }; - - this.handleSubmit = this.handleSubmit.bind(this); - this.handleChange = this.handleChange.bind(this); - this.handleChange2 = this.handleChange2.bind(this); - } - - - - handleSubmit(event) { - event.preventDefault(); - axios({ - method: 'post', - url: "http://127.0.0.1:5000/entry/" + this.props.itemdata.uuid, - headers: {'content-type': 'application/json'}, - data: {"id": this.props.itemdata.uuid, "entry": this.props.itemdata.message, "topic": this.props.itemdata.topic, "created_at": this.props.itemdata.created_at, "week_id": this.props.itemdata.week_uuid, day_id: this.props.itemdata.day_uuid} - }).then(result => { - console.log(result.data) - }).catch(error => { - console.log(error); - }) - this.click(); - } - - handleChange(event) { - this.setState({topic: event.target.value}); - this.props.itemdata.topic = event.target.value; - } - - handleChange2(event) { - this.setState({entry: event.target.value}); - this.props.itemdata.message = event.target.value; - } - - renderTopicElement = () => { - - if (this.state.isEditting) { - return
-

Edit

-
-
- -
-
- -
-
-
-
- -
-
- -
-
-
- -
-
- } else { - return
-

{'Topic: ' + this.props.itemdata.topic}

-

{'Entry: ' + this.props.itemdata.message}

-

{'Created on: ' + dateItem}

-
-
-

Notes

-
    - {this.props.itemdata.notes.map(note => -
  • {note.note}
  • - )} -
-
-
-

Blockers

-
    - {this.props.itemdata.blockers.map(blocker => -
  • {blocker.blocker}
  • - )} -
-
-
-

Jira's

-
    - {this.props.itemdata.jiras.map(jira => -
  • {"Ticket: " + jira.jira_ticket + " Tag: " + jira.jira_tag}
  • - )} -
-
-
-
- - Delete -
-
- } - } - - click = () => { - this.setState((state) => ({ - ...state, - isEditting: !state.isEditting - })); - } - +// const dateItem = new Date(data.created_at).toLocaleDateString() +// +// class Entry extends React.Component { +// +// constructor(props) { +// super(props); +// +// this.state = { +// isEditting: false, +// username: '', +// raw_input: '', +// created_at: '' +// }; +// +// this.handleSubmit = this.handleSubmit.bind(this); +// this.handleChange = this.handleChange.bind(this); +// this.handleChange2 = this.handleChange2.bind(this); +// } +// +// +// +// handleSubmit(event) { +// event.preventDefault(); +// axios({ +// method: 'post', +// url: "http://127.0.0.1:5000/entry/" + this.props.itemdata.uuid, +// headers: {'content-type': 'application/json'}, +// data: {"id": this.props.itemdata.uuid, "entry": this.props.itemdata.message, "topic": this.props.itemdata.topic, "created_at": this.props.itemdata.created_at, "week_id": this.props.itemdata.week_uuid, day_id: this.props.itemdata.day_uuid} +// }).then(result => { +// console.log(result.data) +// }).catch(error => { +// console.log(error); +// }) +// this.click(); +// } +// +// handleChange(event) { +// this.setState({topic: event.target.value}); +// this.props.itemdata.topic = event.target.value; +// } +// +// handleChange2(event) { +// this.setState({entry: event.target.value}); +// this.props.itemdata.message = event.target.value; +// } +// +// renderTopicElement = () => { +// +// if (this.state.isEditting) { +// return
+//

Edit

+//
+//
+// +//
+//
+// +//
+//
+//
+//
+// +//
+//
+// +//
+//
+//
+// +//
+//
+// } else { +// return
+//

{'Topic: ' + this.props.itemdata.topic}

+//

{'Entry: ' + this.props.itemdata.message}

+//

{'Created on: ' + dateItem}

+//
+// {/*
*/} +// {/*

Notes

*/} +// {/*
    */} +// {/* {this.props.itemdata.notes.map(note =>*/} +// {/*
  • {note.note}
  • */} +// {/* )}*/} +// {/*
*/} +// {/*
*/} +// {/*
*/} +// {/*

Blockers

*/} +// {/*
    */} +// {/* {this.props.itemdata.blockers.map(blocker =>*/} +// {/*
  • {blocker.blocker}
  • */} +// {/* )}*/} +// {/*
*/} +// {/*
*/} +// {/*
*/} +// {/*

Jira's

*/} +// {/*
    */} +// {/* {this.props.itemdata.jiras.map(jira =>*/} +// {/*
  • {"Ticket: " + jira.jira_ticket + " Tag: " + jira.jira_tag}
  • */} +// {/* )}*/} +// {/*
*/} +// {/*
*/} +//
+//
+// +// Delete +//
+//
+// } +// } +// +// click = () => { +// this.setState((state) => ({ +// ...state, +// isEditting: !state.isEditting +// })); +// } +// +// render() { +// return ( +//
+// {this.renderTopicElement()} +//
+// ); +// } +// } + +class ReportItem extends React.Component { render() { return ( -
- {this.renderTopicElement()} +
+
+

Report

+

{this.props.report["raw_input"]}

+
); } } - -function App() { - return ( -
- -
- ) +const App = () => { + const [reportData, setReportData] = useState({}); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + fetch(`/getlist`) + .then((response) => { + if (!response.ok) { + throw new Error( + `This is an HTTP error: The status is ${response.status}` + ); + } + return response.json(); + }) + .then((actualData) => { + setReportData(actualData[0]); + setError(null); + }) + .catch((err) => { + setError(err.message); + setReportData(null) + }) + .finally(() => { + setLoading(false); + }); + }, []); + + if (loading) { + return ( +
{`There is a problem fetching the post data - ${error}`}
+ ) + } else { + if (reportData != null) { + return ( +
+ ) + } else { + return ( +
+ {/**/} +
+ ) + } + } } -ReactDOM.render(, rootElement); \ No newline at end of file +const domContainer = document.querySelector("#root"); +ReactDOM.render(, domContainer); + + +// function App() { +// return ( +//
+// +//
+// ) +// } +// +// ReactDOM.render(, rootElement); \ No newline at end of file diff --git a/DirectReport/browserview/templates/detail.html b/DirectReport/browserview/templates/detail.html index 324a6d8f..17fd023c 100644 --- a/DirectReport/browserview/templates/detail.html +++ b/DirectReport/browserview/templates/detail.html @@ -5,5 +5,8 @@ {% block content %}
+
+
-{% endblock %} \ No newline at end of file +{% endblock %} + diff --git a/DirectReport/models/report_builder.py b/DirectReport/models/report_builder.py index e08c60ab..89277c71 100644 --- a/DirectReport/models/report_builder.py +++ b/DirectReport/models/report_builder.py @@ -48,7 +48,7 @@ def get_reports_for_user_id(user_id): :param entry_id: The ID of the entry to delete. """ storage = ReportModel('ReportStorage.db') - user_reports = storage.get_report(user_id) + user_reports = storage.get_reports_userid(user_id) return user_reports @staticmethod diff --git a/DirectReport/models/report_model.py b/DirectReport/models/report_model.py index cea02719..86b232d1 100644 --- a/DirectReport/models/report_model.py +++ b/DirectReport/models/report_model.py @@ -116,6 +116,7 @@ def list_all_reports_as_dict(self): entry = Report(*result) entry_dict = entry.to_dict() results_list.append(entry_dict) + print(results_list) return results_list def list_all_reports(self): @@ -131,3 +132,26 @@ def list_all_reports(self): ) results = cursor.fetchall() return results + + def get_reports_userid(self, user_id): + """ + Retrieves an `Entry` object from the SQLite database by its UUID. + :param uuid: The UUID of the entry to retrieve. + :return: The `Entry` object if found, otherwise `None`. + """ + cursor = self.conn.cursor() + result = cursor.execute( + "SELECT uuid, user_id, raw_input, report, created_at FROM reports WHERE user_id = ?", + (str(user_id),), + ) + results = cursor.fetchall() + results_list = [] + for result in results: + entry = Report(*result) + entry_dict = entry.to_dict() + results_list.append(entry_dict) + return results_list + # if row: + # return Report(*row) + # else: + # return None From 50c059a1e91ff1a91a909bc34da1659a51d94943 Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Sun, 10 Dec 2023 19:46:02 -0500 Subject: [PATCH 14/21] remove note js original --- DirectReport/browserview/static/js/note.js | 136 --------------------- 1 file changed, 136 deletions(-) diff --git a/DirectReport/browserview/static/js/note.js b/DirectReport/browserview/static/js/note.js index 0f5c89a8..019d57b8 100644 --- a/DirectReport/browserview/static/js/note.js +++ b/DirectReport/browserview/static/js/note.js @@ -4,131 +4,6 @@ const { useState, useEffect } = React; const rootElement = document.getElementById('root') -// const dateItem = new Date(data.created_at).toLocaleDateString() -// -// class Entry extends React.Component { -// -// constructor(props) { -// super(props); -// -// this.state = { -// isEditting: false, -// username: '', -// raw_input: '', -// created_at: '' -// }; -// -// this.handleSubmit = this.handleSubmit.bind(this); -// this.handleChange = this.handleChange.bind(this); -// this.handleChange2 = this.handleChange2.bind(this); -// } -// -// -// -// handleSubmit(event) { -// event.preventDefault(); -// axios({ -// method: 'post', -// url: "http://127.0.0.1:5000/entry/" + this.props.itemdata.uuid, -// headers: {'content-type': 'application/json'}, -// data: {"id": this.props.itemdata.uuid, "entry": this.props.itemdata.message, "topic": this.props.itemdata.topic, "created_at": this.props.itemdata.created_at, "week_id": this.props.itemdata.week_uuid, day_id: this.props.itemdata.day_uuid} -// }).then(result => { -// console.log(result.data) -// }).catch(error => { -// console.log(error); -// }) -// this.click(); -// } -// -// handleChange(event) { -// this.setState({topic: event.target.value}); -// this.props.itemdata.topic = event.target.value; -// } -// -// handleChange2(event) { -// this.setState({entry: event.target.value}); -// this.props.itemdata.message = event.target.value; -// } -// -// renderTopicElement = () => { -// -// if (this.state.isEditting) { -// return
-//

Edit

-//
-//
-// -//
-//
-// -//
-//
-//
-//
-// -//
-//
-// -//
-//
-//
-// -//
-//
-// } else { -// return
-//

{'Topic: ' + this.props.itemdata.topic}

-//

{'Entry: ' + this.props.itemdata.message}

-//

{'Created on: ' + dateItem}

-//
-// {/*
*/} -// {/*

Notes

*/} -// {/*
    */} -// {/* {this.props.itemdata.notes.map(note =>*/} -// {/*
  • {note.note}
  • */} -// {/* )}*/} -// {/*
*/} -// {/*
*/} -// {/*
*/} -// {/*

Blockers

*/} -// {/*
    */} -// {/* {this.props.itemdata.blockers.map(blocker =>*/} -// {/*
  • {blocker.blocker}
  • */} -// {/* )}*/} -// {/*
*/} -// {/*
*/} -// {/*
*/} -// {/*

Jira's

*/} -// {/*
    */} -// {/* {this.props.itemdata.jiras.map(jira =>*/} -// {/*
  • {"Ticket: " + jira.jira_ticket + " Tag: " + jira.jira_tag}
  • */} -// {/* )}*/} -// {/*
*/} -// {/*
*/} -//
-//
-// -// Delete -//
-//
-// } -// } -// -// click = () => { -// this.setState((state) => ({ -// ...state, -// isEditting: !state.isEditting -// })); -// } -// -// render() { -// return ( -//
-// {this.renderTopicElement()} -//
-// ); -// } -// } class ReportItem extends React.Component { render() { @@ -191,14 +66,3 @@ const App = () => { const domContainer = document.querySelector("#root"); ReactDOM.render(, domContainer); - - -// function App() { -// return ( -//
-// -//
-// ) -// } -// -// ReactDOM.render(, rootElement); \ No newline at end of file From 7f437d876acdbb06bf85f2697d96cd31e222b43b Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Mon, 11 Dec 2023 03:37:26 -0500 Subject: [PATCH 15/21] add new metrics to display --- DirectReport/browserview/app.py | 6 +- DirectReport/browserview/modelclient.py | 34 ++++--- DirectReport/browserview/static/js/account.js | 39 ++++---- .../browserview/static/js/chart_helper.js | 94 ++++++++++++++----- DirectReport/browserview/static/js/note.js | 8 +- DirectReport/browserview/static/js/signup.js | 44 +++------ .../browserview/static/js/teammember.js | 2 +- .../browserview/static/js/teamreport.js | 74 ++++++++------- .../browserview/templates/account.html | 1 + 9 files changed, 181 insertions(+), 121 deletions(-) diff --git a/DirectReport/browserview/app.py b/DirectReport/browserview/app.py index fd1fe44b..76bf13b7 100644 --- a/DirectReport/browserview/app.py +++ b/DirectReport/browserview/app.py @@ -95,6 +95,9 @@ def account(): @login_required def account_data(): saved_reports = ReportBuilder.get_reports_for_user_id(current_user.id) + logitem = "Adrian Prantl (67):\n add mangling testcase\n Debug Info: Represent private discriminators in DWARF.\n Revert \"Debug Info: Represent private discriminators in DWARF.\"\n Debug Info: Represent private discriminators in DWARF.\n Un-XFAIL and update test.\n Move the logic for ignoring the debug locations for closure setup code into SILGen. NFC-ish.\n Debug Info: Associate a function call with the beginning of the expression.\n Debug Info / SILGen: fix the source location of variable assignments\n typo\n Fix the debug locations of inserted operations in AvailableValueAggregator.\n Don't emit shadow copies for anonymous variables.\n Remove dead API IRGenDebugInfo::setArtificialTrapLocation().\n Use compiler-generated location for func.-sig.-spec. thunks\n whitespace\n Fix the missing inlined-at field of function-level SILDebugScopes.\n Add debug info support for inlined and specialized generic variables.\n Revert \"Add debug info support for inlined and specialized generic variables.\"\n Add debug info support for inlined and specialized generic variables.\n Update mangling prefix in Mangling.rst\n Add initial support for debug info for coroutine allocas.\n Temporarily disable failing test case, rdar://problem/43340064\n Add build-script support for the Swift LLDB backwards-compatibility tests.\n Remove accidentally committed debugging code\n Deserialize Swift compatibility version in CompilerInvocation::loadFromSerializedAST()\n SILGen: Preserve function argument debug info for arguments needing alloc_stack\n Use as the filename for SILLocation-less functions to avoid misleading source locatio\nns in backtraces.\n Add a -verify-linetable LLVM option.\n Enable debug info for inlined generics by default. It works now.\n Fix nonasserts compilation\n\nAhmad Alhashemi (5):\n [Parser] Detect nonbreaking space U+00A0 and fixit\n Move non-breaking space handling to lexUnknown\n Add more non-breaking space test cases\n Minor style edits\n Add tests for non-breaking space detect and fix-it\n\nAkshay Shrimali (1):\n Update README.md\n\nAlan Zeino (1):\n Fix typo in code example in libSyntax README\n\nAlbin \"albinek\" Sadowski (1):\n Fix syntax highlighting in CHANGELOG (#15107)\n\nAlejandro (3):\n Remove a warning, some doc fixes (#16863)\n [SR-8178] Fix BinaryFloatingPoint.random(in:) open range returning upperBound (#17794)\n [Docs] Fix minor code typo in SILPro..Man..md\n\nAlex Blewitt (5):\n [SR-7032] Fix compare for lhs and rhs\n [SR-7036] Use || instead of && for kind comparison\n [SR-7041] Remove duplicate conditional check\n Remove duplicate verb\n [SR-7043] Remove duplicate if statement" + client = GithubClient() + shortlog = client.parse_git_shortlog(logitem) report_results = [] for report in saved_reports: report_element = { @@ -112,7 +115,8 @@ def account_data(): } user_element = { "user": user_account, - "reports": report_results + "reports": report_results, + "shortlog": shortlog } return user_element, 201 diff --git a/DirectReport/browserview/modelclient.py b/DirectReport/browserview/modelclient.py index 16864df4..53f7723f 100644 --- a/DirectReport/browserview/modelclient.py +++ b/DirectReport/browserview/modelclient.py @@ -11,9 +11,14 @@ "commits": "67" }, { - "name": "Ahmad Alhashemi", - "accomplishments": "Ahmad worked on the Parser, detecting non breaking space U+00A0 and providing a fix.He also made minor style edits and added more non-breaking space testcases.", - "commits": "5" + "name": "Alan Zeino", + "accomplishments": "Alan fixed a typo in the code example in libSyntax README.", + "commits": "1" + }, + { + "name": "Alejandro", + "accomplishments": "Alejandro removed awarning, made some documentation fixes, fixed Binary Floating Point. random(in:) open range returning upperBound, and fixed a minor code typo in SILPro.", + "commits": "3" }, { "name": "Akshay Shrimali", @@ -21,20 +26,15 @@ "commits": "1" }, { - "name": "Alan Zeino", - "accomplishments": "Alan fixed a typo in the code example in libSyntax README.", - "commits": "1" + "name": "Ahmad Alhashemi", + "accomplishments": "Ahmad worked on the Parser, detecting non breaking space U+00A0 and providing a fix.He also made minor style edits and added more non-breaking space testcases.", + "commits": "5" }, { "name": "Albin \"albinek\" Sadowski", "accomplishments": "Albin fixed syntax highlighting in CHANGELOG.", "commits": "1" }, - { - "name": "Alejandro", - "accomplishments": "Alejandro removed awarning, made some documentation fixes, fixed Binary Floating Point. random(in:) open range returning upperBound, and fixed a minor code typo in SILPro.", - "commits": "3" - }, { "name": "Alex Blewitt", "accomplishments": "Alex worked on several fixes including compare for lhs and rhs, using || instead of && for kind comparison,removing duplicate conditional check and duplicate if statement.", @@ -60,6 +60,16 @@ } ], "conclusion": "The team demonstrated good progress this week, with a focus on enhancing DebugInfo and SILGen, improving the Parser, and implementing various fixes. The team should continue to focus on these areas in the coming week." - } + }, + "broad_categories": { + "debug_info": 16, + "code_maintenance": 9, + "documentation": 7, + "test_related": 6, + "nonbreaking_space_handling": 5, + "readme_update": 1, + "syntax_fix": 1 + } + } diff --git a/DirectReport/browserview/static/js/account.js b/DirectReport/browserview/static/js/account.js index ffa765b2..04f5c0fb 100644 --- a/DirectReport/browserview/static/js/account.js +++ b/DirectReport/browserview/static/js/account.js @@ -3,6 +3,7 @@ const { useState, useEffect } = React; const Account = () => { const [userData, setUserData] = useState({}); + const [actualData, setActualData] = useState({}); const [reportData, setReportData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -18,12 +19,16 @@ const Account = () => { return response.json(); }) .then((actualData) => { + console.log(actualData) setUserData(actualData["user"]); setReportData(actualData["reports"]); + setActualData(actualData); setError(null); + // showGraphics(actualData); }) .catch((err) => { - setError(err.message); + // setError(err.message); + // showGraphics(null); setUserData(null) setReportData(null) }) @@ -32,36 +37,39 @@ const Account = () => { }); }, []); + + if (loading) { return (
{`There is a problem fetching the post data - ${error}`}
) } else { + // {showGraphics(actualData)} return (
-

Account: {userData.name}

-

{userData.username}

-

Number of reports saved: {reportData.length}

- {/*{reportData && reportData.map(hightlight =>*/} - {/*

{hightlight.report.raw_input}

*/} - {/*)}*/} +
+

Account: {userData.name}

+

Email: {userData.userid}

+

Username: {userData.username}

+

Number of reports saved {reportData.length}

+
-

Account: {userData.userid}

- - - +
-

Previous Reports

diff --git a/DirectReport/browserview/static/js/chart_helper.js b/DirectReport/browserview/static/js/chart_helper.js index de6c8b43..cb6e2cfa 100644 --- a/DirectReport/browserview/static/js/chart_helper.js +++ b/DirectReport/browserview/static/js/chart_helper.js @@ -1,45 +1,95 @@ function showGraphics(data) { const newData = data - const stringData = JSON.stringify(newData['shortlog']); - const values = Object.keys(newData['shortlog']).map(function(key){ - return Number(newData['shortlog'][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])] }); - console.log(values); - const dataset = values - const chartWidth = 240 - const chartHeight = 120 - const padding = 20 - const heightScalingFactor = chartHeight / getMax(dataset) - const svg = d3 - .select('#map-container') + const chartWidth = 400 + const chartHeight = 300 + const padding = 35 + var data = values + const heightScalingFactor = chartHeight / 67 + var container = d3.select('#map-container') .append('svg') .attr('width', chartWidth) .attr('height', chartHeight) - svg.selectAll('rect') - .data(dataset) + var svg = d3.select("svg") + var groups = svg.selectAll(".groups") + .data(data) .enter() - .append('rect') + .append("g") + .attr("class", "gbar"); + + groups.append("rect") .attr('x', function (value, index) { - return (index * (chartWidth / dataset.length)) + padding + if (index === 0) { + return 0 + } else { + return (index * (chartWidth / data.length)) + } }) .attr('y', function (value, index) { - return chartHeight - (value * heightScalingFactor) + return (chartHeight - 18) - (value[1] * 20) + }) + .attr("width", function (value, index) { + return (chartWidth / data.length) - padding }) - .attr('width', (chartWidth / dataset.length) - padding) - .attr('height', function (value, index) { - return value * heightScalingFactor + .attr("height", function (value, index) { + return value[1] * 20 }) - .attr('fill', 'pink') + .attr("fill", "teal"); -} + groups.append("text") + .attr('x', function (value, index) { + if (index == 0) { + return 0 + } else { + return (index * (chartWidth / data.length)) + } + }) + .attr('y', function (value, index) { + return (chartHeight + 5) + }) + .attr("dy", "-1em") + .style("font-size", "11px") + .style("text-anchor", "center") + .text(function (value, index) { + return value[0].split("_")[0].slice(0, 8) + }) +} function getMax(collection) { var max = 0 collection.forEach(function (element) { max = element > max ? element : max }) return max -} \ No newline at end of file +} + + // function wrap(text, width) { + // text.each(function() { + // let text = d3.select(this), + // words = text.text().split(/\s+/).reverse(), + // word, + // line = [], + // lineNumber = 0, + // lineHeight = 1.1, // ems + // x = text.attr("x"), + // y = text.attr("y"), + // dy = 1.1, + // tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em"); + // while (word = words.pop()) { + // line.push(word); + // tspan.text(line.join(" ")); + // if (tspan.node().getComputedTextLength() > width) { + // line.pop(); + // tspan.text(line.join(" ")); + // line = [word]; + // tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); + // } + // } + // }); + // } \ No newline at end of file diff --git a/DirectReport/browserview/static/js/note.js b/DirectReport/browserview/static/js/note.js index 019d57b8..1808fc26 100644 --- a/DirectReport/browserview/static/js/note.js +++ b/DirectReport/browserview/static/js/note.js @@ -1,10 +1,6 @@ 'use strict'; -const elem = React.createElement; const { useState, useEffect } = React; - -const rootElement = document.getElementById('root') - class ReportItem extends React.Component { render() { return ( @@ -52,7 +48,9 @@ const App = () => { } else { if (reportData != null) { return ( -
+
+ +
) } else { return ( diff --git a/DirectReport/browserview/static/js/signup.js b/DirectReport/browserview/static/js/signup.js index f94f3c4c..7e4b3ff8 100644 --- a/DirectReport/browserview/static/js/signup.js +++ b/DirectReport/browserview/static/js/signup.js @@ -11,54 +11,37 @@ const SignupForm = () => {
-
-
-
-
- - + +
- +
-
diff --git a/DirectReport/browserview/static/js/teammember.js b/DirectReport/browserview/static/js/teammember.js index 8c0a762c..83929653 100644 --- a/DirectReport/browserview/static/js/teammember.js +++ b/DirectReport/browserview/static/js/teammember.js @@ -31,7 +31,7 @@ const TeamMember = () => { if (loading) { return ( -
{`There is a problem fetching the post data - ${error}`}
+
{`There is a problem fetching the data - ${error}`}
) } else { return ( diff --git a/DirectReport/browserview/static/js/teamreport.js b/DirectReport/browserview/static/js/teamreport.js index e8f8a0bb..055d96b9 100644 --- a/DirectReport/browserview/static/js/teamreport.js +++ b/DirectReport/browserview/static/js/teamreport.js @@ -23,6 +23,7 @@ const TeamData = () => { }).then(function(res) { return res.json(); }).then(function(data) { + console.log(data); setTeamData(data); toggle(); showGraphics(data); @@ -104,18 +105,18 @@ const TeamData = () => { const formUI = () => { return ( -
+

Enter Github Data

-
+
-
-
@@ -138,27 +139,27 @@ const TeamData = () => {

Generate Team Report From Metadata

-
+
{formUI()}
-
+

Summary

-
+
{isOpened && ( -
+

{teamData["report"] !== undefined ? -

{teamData["report"]["summary"]}
: null +
{teamData["report"]["summary"]}
: null }

-
-
    +
    +
      {teamData["report"] && teamData["report"]["highlights"].map(hightlight => -
    • -

      {hightlight.title}

      -

      {hightlight.description}

      +
    • +

      {hightlight.title}

      +

      {hightlight.description}

    • )}
    @@ -169,17 +170,21 @@ const TeamData = () => {
-
+

Team

{popoverUI()} -
+ {isOpened && ( -
-
- {teamData["team"] && - teamData["team"].map(teammember => - - )} +
+
+
+ {teamData["team"] && + teamData["team"].map(teammember => + + )} +
)} @@ -187,24 +192,27 @@ const TeamData = () => {
{isOpened && ( -
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/DirectReport/browserview/templates/account.html b/DirectReport/browserview/templates/account.html index 6b33ddf8..75bb8ee6 100644 --- a/DirectReport/browserview/templates/account.html +++ b/DirectReport/browserview/templates/account.html @@ -16,5 +16,6 @@
+
{% endblock %} \ No newline at end of file From d7e1b882c3aca5ac0398fef01c7cc6583adf5704 Mon Sep 17 00:00:00 2001 From: chriswebb09 Date: Mon, 11 Dec 2023 06:44:07 -0500 Subject: [PATCH 16/21] cleanup dashboard ui --- .../browserview/static/js/chart_helper.js | 136 +++++++++++++++++- .../browserview/static/js/teamreport.js | 93 ++++++------ .../browserview/templates/_footer.html | 2 +- DirectReport/browserview/templates/index.html | 3 +- .../browserview/templates/teamreport.html | 4 +- 5 files changed, 182 insertions(+), 56 deletions(-) diff --git a/DirectReport/browserview/static/js/chart_helper.js b/DirectReport/browserview/static/js/chart_helper.js index cb6e2cfa..70327cdc 100644 --- a/DirectReport/browserview/static/js/chart_helper.js +++ b/DirectReport/browserview/static/js/chart_helper.js @@ -1,17 +1,17 @@ -function showGraphics(data) { +function showGraphics(data, divtag) { 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 chartWidth = 400 + const chartWidth = 350 const chartHeight = 300 - const padding = 35 + const padding = 25 var data = values const heightScalingFactor = chartHeight / 67 - var container = d3.select('#map-container') + var container = d3.select(divtag) .append('svg') .attr('width', chartWidth) .attr('height', chartHeight) @@ -42,6 +42,132 @@ function showGraphics(data) { }) .attr("fill", "teal"); + groups.append("text") + .attr('x', function (value, index) { + if (index == 0) { + return 0 + } else { + return (index * (chartWidth / data.length)) + } + + }) + .attr('y', function (value, index) { + return (chartHeight + 10) + }) + .attr("dy", "-1em") + .style("font-size", "11px") + .style("text-anchor", "center") + .text(function (value, index) { + return value[0].split("_")[0].slice(0, 6) + }) +} + +function showGraphics2(data, divtag) { + 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 chartWidth = 350 + const chartHeight = 300 + const padding = 25 + var data = values + const heightScalingFactor = chartHeight / 67 + var container = d3.select(divtag) + .append('svg') + .attr('width', chartWidth) + .attr('height', chartHeight) + + var svg = d3.select(divtag).select("svg") + var groups = svg.selectAll(".groups") + .data(data) + .enter() + .append("g") + .attr("class", "gbar"); + + groups.append("rect") + .attr('x', function (value, index) { + if (index === 0) { + return 0 + } else { + return (index * (chartWidth / data.length)) + } + }) + .attr('y', function (value, index) { + return (chartHeight - 18) - (value[1] * 20) + }) + .attr("width", function (value, index) { + return (chartWidth / data.length) - padding + }) + .attr("height", function (value, index) { + return value[1] * 20 + }) + .attr("fill", "steelblue"); + + groups.append("text") + .attr('x', function (value, index) { + if (index == 0) { + return 0 + } else { + return (index * (chartWidth / data.length)) + } + + }) + .attr('y', function (value, index) { + return (chartHeight + 5) + }) + .attr("dy", "-1em") + .style("font-size", "11px") + .style("text-anchor", "center") + .text(function (value, index) { + return value[0].split("_")[0].slice(0, 6) + }) +} + +function showGraphics3(data, divtag) { + 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 chartWidth = 350 + const chartHeight = 300 + const padding = 25 + var data = values + const heightScalingFactor = chartHeight / 67 + var container = d3.select(divtag) + .append('svg') + .attr('width', chartWidth) + .attr('height', chartHeight) + + var svg = d3.select(divtag).select("svg") + var groups = svg.selectAll(".groups") + .data(data) + .enter() + .append("g") + .attr("class", "gbar"); + + groups.append("rect") + .attr('x', function (value, index) { + if (index === 0) { + return 0 + } else { + return (index * (chartWidth / data.length)) + } + }) + .attr('y', function (value, index) { + return (chartHeight - 18) - (value[1] * 20) + }) + .attr("width", function (value, index) { + return (chartWidth / data.length) - padding + }) + .attr("height", function (value, index) { + return value[1] * 20 + }) + .attr("fill", "yellow"); + groups.append("text") .attr('x', function (value, index) { if (index == 0) { @@ -58,7 +184,7 @@ function showGraphics(data) { .style("font-size", "11px") .style("text-anchor", "center") .text(function (value, index) { - return value[0].split("_")[0].slice(0, 8) + return value[0].split("_")[0].slice(0, 6) }) } function getMax(collection) { diff --git a/DirectReport/browserview/static/js/teamreport.js b/DirectReport/browserview/static/js/teamreport.js index 055d96b9..b6d57d05 100644 --- a/DirectReport/browserview/static/js/teamreport.js +++ b/DirectReport/browserview/static/js/teamreport.js @@ -26,7 +26,9 @@ const TeamData = () => { console.log(data); setTeamData(data); toggle(); - showGraphics(data); + showGraphics(data, '#map-container'); + showGraphics2(data, '#map-container2'); + showGraphics3(data, '#map-container3'); }).then(function() { console.log('done'); @@ -105,14 +107,14 @@ const TeamData = () => { const formUI = () => { return ( -
+
-

Enter +

Enter Github Data

-
@@ -136,26 +138,28 @@ const TeamData = () => { return (
-

+

Generate Team Report From Metadata

-
-
+
+
{formUI()}
-
-
-

Summary

-
+ +
+
+

Summary

+
{isOpened && ( -
+

{teamData["report"] !== undefined ? -

{teamData["report"]["summary"]}
: null +
{teamData["report"]["summary"]}
: null }

-
-
    +
    +
      {teamData["report"] && teamData["report"]["highlights"].map(hightlight =>
    • {hightlight.title}

      @@ -169,51 +173,46 @@ const TeamData = () => {
-
-
-

Team

+
+
+

Team

{popoverUI()} - +
{isOpened && ( -
-
-
- {teamData["team"] && - teamData["team"].map(teammember => - - )} -
+
+
+ {teamData["team"] && + teamData["team"].map(teammember => + + )}
)}
+ {isOpened && ( -
-
-
-
-
+
+

+ Data +

+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
diff --git a/DirectReport/browserview/templates/_footer.html b/DirectReport/browserview/templates/_footer.html index 910d6eb4..36990b57 100644 --- a/DirectReport/browserview/templates/_footer.html +++ b/DirectReport/browserview/templates/_footer.html @@ -1,4 +1,4 @@ -