From 4c67c744fb7967a79c5436b5e102796702272283 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Mon, 2 Dec 2024 14:00:16 -0500 Subject: [PATCH 01/75] Title change --- app/src/Home.py | 2 +- app/src/pages/12_API_Test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/Home.py b/app/src/Home.py index ef0f7b19ad..37d5e9116b 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -34,7 +34,7 @@ # set the title of the page and provide a simple prompt. logger.info("Loading the Home page of the app") -st.title('CS 3200 Sample Semester Project App') +st.title('TRACE For Co Ops') st.write('\n\n') st.write('### HI! As which user would you like to log in?') diff --git a/app/src/pages/12_API_Test.py b/app/src/pages/12_API_Test.py index 74883c5a85..93a97e11eb 100644 --- a/app/src/pages/12_API_Test.py +++ b/app/src/pages/12_API_Test.py @@ -17,7 +17,7 @@ """ data = {} try: - data = requests.get('http://api:4000/data').json() + data = requests.get('http://api:4000/p/products').json() except: st.write("**Important**: Could not connect to sample api, so using dummy data.") data = {"a":{"b": "123", "c": "hello"}, "z": {"b": "456", "c": "goodbye"}} From 0003d1a7b7f23c9abcf7ea4d3812d0ecdb094e25 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Mon, 2 Dec 2024 14:04:05 -0500 Subject: [PATCH 02/75] user log in buttons --- app/src/Home.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/Home.py b/app/src/Home.py index 37d5e9116b..586db37d92 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -42,7 +42,7 @@ # functionality, we put a button on the screen that the user # can click to MIMIC logging in as that mock user. -if st.button("Act as John, a Political Strategy Advisor", +if st.button("Act as Sebastian, a Student Co Op Searcher", type = 'primary', use_container_width=True): # when user clicks the button, they are now considered authenticated @@ -57,7 +57,7 @@ logger.info("Logging in as Political Strategy Advisor Persona") st.switch_page('pages/00_Pol_Strat_Home.py') -if st.button('Act as Mohammad, an USAID worker', +if st.button('Act as Riley, a student Co-Op Reviewer', type = 'primary', use_container_width=True): st.session_state['authenticated'] = True @@ -74,4 +74,11 @@ st.switch_page('pages/20_Admin_Home.py') +if st.button('Act as Annalise, an Analyist of Site Performance', + type = 'primary', + use_container_width=True): + st.session_state['authenticated'] = True + st.session_state['role'] = 'administrator' + st.session_state['first_name'] = 'SysAdmin' + st.switch_page('pages/20_Admin_Home.py') From 15ef2a095e3a2632a2149319ef45aac1ed896e5e Mon Sep 17 00:00:00 2001 From: sevensrig Date: Mon, 2 Dec 2024 17:16:41 -0500 Subject: [PATCH 03/75] Seb CoOp Searcher Button implemented --- app/src/Home.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/Home.py b/app/src/Home.py index 586db37d92..01f167a44f 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -48,14 +48,14 @@ # when user clicks the button, they are now considered authenticated st.session_state['authenticated'] = True # we set the role of the current user - st.session_state['role'] = 'pol_strat_advisor' + st.session_state['role'] = 'Co-Op searcher' # we add the first name of the user (so it can be displayed on # subsequent pages). - st.session_state['first_name'] = 'John' + st.session_state['first_name'] = 'Sebastian' # finally, we ask streamlit to switch to another page, in this case, the # landing page for this particular user type - logger.info("Logging in as Political Strategy Advisor Persona") - st.switch_page('pages/00_Pol_Strat_Home.py') + logger.info("Logging in as Co-Op Searcher") + st.switch_page('pages/100_CoOp_Searcher_Home.py') if st.button('Act as Riley, a student Co-Op Reviewer', type = 'primary', @@ -63,7 +63,7 @@ st.session_state['authenticated'] = True st.session_state['role'] = 'usaid_worker' st.session_state['first_name'] = 'Mohammad' - st.switch_page('pages/10_USAID_Worker_Home.py') + st.switch_page('pages/100_CoOp_Searcher_Home.py') if st.button('Act as System Administrator', type = 'primary', From 1236c6396b8e91b8533ac5e5d172680eae956f29 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Mon, 2 Dec 2024 17:17:15 -0500 Subject: [PATCH 04/75] Home page for CoOpSearcher --- app/src/pages/100_CoOp_Searcher_Home.py | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 app/src/pages/100_CoOp_Searcher_Home.py diff --git a/app/src/pages/100_CoOp_Searcher_Home.py b/app/src/pages/100_CoOp_Searcher_Home.py new file mode 100644 index 0000000000..d3580e48a1 --- /dev/null +++ b/app/src/pages/100_CoOp_Searcher_Home.py @@ -0,0 +1,35 @@ +import logging +logger = logging.getLogger(__name__) + +import streamlit as st +from modules.nav import SideBarLinks + +st.set_page_config(layout = 'wide') + +# Show appropriate sidebar links for the role of the currently logged in user +SideBarLinks() + +st.title(f"Welcome Co-op searcher, {st.session_state['first_name']}.") +st.write('') +st.write('') +st.write('### What would you like to do today?') + +if st.button('View Company and Position Reviews', + type='primary', + use_container_width=True): + st.switch_page('pages/01_World_Bank_Viz.py') + +if st.button('View Interview Information', + type='primary', + use_container_width=True): + st.switch_page('pages/02_Map_Demo.py') + +if st.button('View Positions with Matching Skills', + type='primary', + use_container_width=True): + st.switch_page('pages/02_Map_Demo.py') + +if st.button('Enter My Interview Experiences', + type='primary', + use_container_width=True): + st.switch_page('pages/02_Map_Demo.py') \ No newline at end of file From e48474ac6d2b0a83a3e1851ce2c17341f213c9e0 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Mon, 2 Dec 2024 17:46:48 -0500 Subject: [PATCH 05/75] CoOp Searcher subpages created --- app/src/pages/101_Company_Position_Reviews.py | 41 +++++++++++++++++++ app/src/pages/102_Interview_Information.py | 19 +++++++++ app/src/pages/103_Skill_Matching.py | 41 +++++++++++++++++++ app/src/pages/104_Enter_Interview_Info.py | 20 +++++++++ 4 files changed, 121 insertions(+) create mode 100644 app/src/pages/101_Company_Position_Reviews.py create mode 100644 app/src/pages/102_Interview_Information.py create mode 100644 app/src/pages/103_Skill_Matching.py create mode 100644 app/src/pages/104_Enter_Interview_Info.py diff --git a/app/src/pages/101_Company_Position_Reviews.py b/app/src/pages/101_Company_Position_Reviews.py new file mode 100644 index 0000000000..c02f6ec1a8 --- /dev/null +++ b/app/src/pages/101_Company_Position_Reviews.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Find Company and Position Reviews') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) diff --git a/app/src/pages/102_Interview_Information.py b/app/src/pages/102_Interview_Information.py new file mode 100644 index 0000000000..906f4c915a --- /dev/null +++ b/app/src/pages/102_Interview_Information.py @@ -0,0 +1,19 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View Interview Information and Tips') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") diff --git a/app/src/pages/103_Skill_Matching.py b/app/src/pages/103_Skill_Matching.py new file mode 100644 index 0000000000..66b5ec8483 --- /dev/null +++ b/app/src/pages/103_Skill_Matching.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Find positions with matching skills') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) diff --git a/app/src/pages/104_Enter_Interview_Info.py b/app/src/pages/104_Enter_Interview_Info.py new file mode 100644 index 0000000000..034519f390 --- /dev/null +++ b/app/src/pages/104_Enter_Interview_Info.py @@ -0,0 +1,20 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Enter Information about your Interview experiences') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + From 3605c462e39d569ebf45fa8432461b4ba597cefe Mon Sep 17 00:00:00 2001 From: sevensrig Date: Mon, 2 Dec 2024 18:34:40 -0500 Subject: [PATCH 06/75] CoOp Searchers subpages created --- ...ws.py => 1001_Company_Position_Reviews.py} | 0 ...ation.py => 1002_Interview_Information.py} | 0 ...terview_Info.py => 1003_Skill_Matching.py} | 2 +- app/src/pages/1004_Enter_Interview_Info.py | 14 +++++++ app/src/pages/100_CoOp_Searcher_Home.py | 19 ++++----- app/src/pages/103_Skill_Matching.py | 41 ------------------- 6 files changed, 24 insertions(+), 52 deletions(-) rename app/src/pages/{101_Company_Position_Reviews.py => 1001_Company_Position_Reviews.py} (100%) rename app/src/pages/{102_Interview_Information.py => 1002_Interview_Information.py} (100%) rename app/src/pages/{104_Enter_Interview_Info.py => 1003_Skill_Matching.py} (89%) create mode 100644 app/src/pages/1004_Enter_Interview_Info.py delete mode 100644 app/src/pages/103_Skill_Matching.py diff --git a/app/src/pages/101_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py similarity index 100% rename from app/src/pages/101_Company_Position_Reviews.py rename to app/src/pages/1001_Company_Position_Reviews.py diff --git a/app/src/pages/102_Interview_Information.py b/app/src/pages/1002_Interview_Information.py similarity index 100% rename from app/src/pages/102_Interview_Information.py rename to app/src/pages/1002_Interview_Information.py diff --git a/app/src/pages/104_Enter_Interview_Info.py b/app/src/pages/1003_Skill_Matching.py similarity index 89% rename from app/src/pages/104_Enter_Interview_Info.py rename to app/src/pages/1003_Skill_Matching.py index 034519f390..89e64ad220 100644 --- a/app/src/pages/104_Enter_Interview_Info.py +++ b/app/src/pages/1003_Skill_Matching.py @@ -13,7 +13,7 @@ SideBarLinks() # set the header of the page -st.header('Enter Information about your Interview experiences') +st.header('Find positions with matching skills') # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") diff --git a/app/src/pages/1004_Enter_Interview_Info.py b/app/src/pages/1004_Enter_Interview_Info.py new file mode 100644 index 0000000000..c2c14eab75 --- /dev/null +++ b/app/src/pages/1004_Enter_Interview_Info.py @@ -0,0 +1,14 @@ +import logging +logger = logging.getLogger(__name__) +import streamlit as st +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Enter Information about your Interview experiences') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + diff --git a/app/src/pages/100_CoOp_Searcher_Home.py b/app/src/pages/100_CoOp_Searcher_Home.py index d3580e48a1..c5006cd2a3 100644 --- a/app/src/pages/100_CoOp_Searcher_Home.py +++ b/app/src/pages/100_CoOp_Searcher_Home.py @@ -1,6 +1,5 @@ import logging logger = logging.getLogger(__name__) - import streamlit as st from modules.nav import SideBarLinks @@ -15,21 +14,21 @@ st.write('### What would you like to do today?') if st.button('View Company and Position Reviews', - type='primary', + type='primary', use_container_width=True): - st.switch_page('pages/01_World_Bank_Viz.py') + st.switch_page('pages/1001_Company_Position_Reviews.py') if st.button('View Interview Information', - type='primary', + type='primary', use_container_width=True): - st.switch_page('pages/02_Map_Demo.py') - + st.switch_page('pages/1002_Interview_Information.py') + if st.button('View Positions with Matching Skills', - type='primary', + type='primary', use_container_width=True): - st.switch_page('pages/02_Map_Demo.py') + st.switch_page('pages/1003_Skill_Matching.py') if st.button('Enter My Interview Experiences', - type='primary', + type='primary', use_container_width=True): - st.switch_page('pages/02_Map_Demo.py') \ No newline at end of file + st.switch_page('pages/1004_Enter_Interview_Info.py') diff --git a/app/src/pages/103_Skill_Matching.py b/app/src/pages/103_Skill_Matching.py deleted file mode 100644 index 66b5ec8483..0000000000 --- a/app/src/pages/103_Skill_Matching.py +++ /dev/null @@ -1,41 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import pandas as pd -import streamlit as st -from streamlit_extras.app_logo import add_logo -import world_bank_data as wb -import matplotlib.pyplot as plt -import numpy as np -import plotly.express as px -from modules.nav import SideBarLinks - -# Call the SideBarLinks from the nav module in the modules directory -SideBarLinks() - -# set the header of the page -st.header('Find positions with matching skills') - -# You can access the session state to make a more customized/personalized app experience -st.write(f"### Hi, {st.session_state['first_name']}.") - -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) - -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) - - st.pyplot(test_plot) - - -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) From b326e99583812587d8aea44ac3f9fd716ed8f5ab Mon Sep 17 00:00:00 2001 From: sevensrig Date: Wed, 4 Dec 2024 21:26:20 -0500 Subject: [PATCH 07/75] SQL file for database/schema creation --- database-files/10_coopPlatformDB.sql | 143 +++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 database-files/10_coopPlatformDB.sql diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql new file mode 100644 index 0000000000..2c258aaab0 --- /dev/null +++ b/database-files/10_coopPlatformDB.sql @@ -0,0 +1,143 @@ + + +-- Create the database +CREATE DATABASE IF NOT EXISTS CoopPlatform; + + +-- Use the newly created database +USE CoopPlatform; + + +-- Create User table +CREATE TABLE IF NOT EXISTS User ( + userID INT AUTO_INCREMENT PRIMARY KEY, + firstName VARCHAR(50), + lastName VARCHAR(50), + email VARCHAR(100) UNIQUE, + major VARCHAR(50), + skills TEXT, + interests TEXT, + isAdmin BOOLEAN DEFAULT FALSE, + isAnalyst BOOLEAN DEFAULT FALSE +); + + +-- Create Companies table +CREATE TABLE IF NOT EXISTS Companies ( + companyID INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(100), + description TEXT +); + + +-- Create Industries table +CREATE TABLE IF NOT EXISTS Industries ( + industryID INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(100) +); + + +-- Create the relationship table for Industries and Companies +CREATE TABLE IF NOT EXISTS CompanyIndustry ( + companyID INT, + industryID INT, + PRIMARY KEY (companyID, industryID), + FOREIGN KEY (companyID) REFERENCES Companies(companyID), + FOREIGN KEY (industryID) REFERENCES Industries(industryID) +); + + +-- Create Location table +CREATE TABLE IF NOT EXISTS Location ( + locationID INT AUTO_INCREMENT PRIMARY KEY, + companyID INT, + address TEXT, + city VARCHAR(100), + state_province VARCHAR(100), + country VARCHAR(100), + FOREIGN KEY (companyID) REFERENCES Companies(companyID) +); + + +-- Create Role table +CREATE TABLE IF NOT EXISTS Role ( + roleID INT AUTO_INCREMENT PRIMARY KEY, + companyID INT, + locationID INT, + roleName VARCHAR(100), + description TEXT, + skillsRequired TEXT, + FOREIGN KEY (companyID) REFERENCES Companies(companyID), + FOREIGN KEY (locationID) REFERENCES Location(locationID) +); + + +-- Create Reviews table +CREATE TABLE IF NOT EXISTS Reviews ( + reviewID INT AUTO_INCREMENT PRIMARY KEY, + userID INT, + roleID INT, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + updatedAt DATETIME ON UPDATE CURRENT_TIMESTAMP, + publishedAt DATETIME, + reviewType VARCHAR(50), + heading VARCHAR(100), + content TEXT, + views INT DEFAULT 0, + likes INT DEFAULT 0, + isFlagged BOOLEAN DEFAULT FALSE, + FOREIGN KEY (userID) REFERENCES User(userID), + FOREIGN KEY (roleID) REFERENCES Role(roleID) +); + + +-- Create Comments table +CREATE TABLE IF NOT EXISTS Comments ( + commentID INT AUTO_INCREMENT PRIMARY KEY, + reviewID INT, + userID INT, + parentCommentID INT DEFAULT NULL, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + updatedAt DATETIME ON UPDATE CURRENT_TIMESTAMP, + content TEXT, + likes INT DEFAULT 0, + isFlagged BOOLEAN DEFAULT FALSE, + FOREIGN KEY (reviewID) REFERENCES Reviews(reviewID), + FOREIGN KEY (userID) REFERENCES User(userID), + FOREIGN KEY (parentCommentID) REFERENCES Comments(commentID) +); + + +-- Create Badges table +CREATE TABLE IF NOT EXISTS Badges ( + badgeID INT AUTO_INCREMENT PRIMARY KEY, + badgeName VARCHAR(50) +); + + +-- Create the relationship table for User and Badges +CREATE TABLE IF NOT EXISTS UserBadges ( + userID INT, + badgeID INT, + PRIMARY KEY (userID, badgeID), + FOREIGN KEY (userID) REFERENCES User(userID), + FOREIGN KEY (badgeID) REFERENCES Badges(badgeID) +); + + +-- Create Feedback table +CREATE TABLE IF NOT EXISTS Feedback ( + feedbackID INT AUTO_INCREMENT PRIMARY KEY, + userID INT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + header VARCHAR(100), + content TEXT, + FOREIGN KEY (userID) REFERENCES User(userID) +); + + + + + + + From d8a0ccee111b98e89f7be3ddc22046542870e6a9 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:08:20 -0500 Subject: [PATCH 08/75] update subpages for admin --- app/src/pages/3001_Admin_Dashboard.py | 0 app/src/pages/3002_Flagged_Posts.py | 0 app/src/pages/3003_Company_Profiles.py | 0 app/src/pages/3004_User_Feedback.py | 0 app/src/pages/3005_Analytics_and_Trends.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/pages/3001_Admin_Dashboard.py create mode 100644 app/src/pages/3002_Flagged_Posts.py create mode 100644 app/src/pages/3003_Company_Profiles.py create mode 100644 app/src/pages/3004_User_Feedback.py create mode 100644 app/src/pages/3005_Analytics_and_Trends.py diff --git a/app/src/pages/3001_Admin_Dashboard.py b/app/src/pages/3001_Admin_Dashboard.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/3003_Company_Profiles.py b/app/src/pages/3003_Company_Profiles.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/3005_Analytics_and_Trends.py b/app/src/pages/3005_Analytics_and_Trends.py new file mode 100644 index 0000000000..e69de29bb2 From 4c53adbcab06609378f2ed5f025c762d7eb39fba Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:10:08 -0500 Subject: [PATCH 09/75] create admi --- .../pages/300_System_Administrator_Home.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 app/src/pages/300_System_Administrator_Home.py diff --git a/app/src/pages/300_System_Administrator_Home.py b/app/src/pages/300_System_Administrator_Home.py new file mode 100644 index 0000000000..b3c9d582b1 --- /dev/null +++ b/app/src/pages/300_System_Administrator_Home.py @@ -0,0 +1,40 @@ +import logging +logger = logging.getLogger(__name__) +import streamlit as st +from modules.nav import SideBarLinks + +st.set_page_config(layout = 'wide') + +# Show appropriate sidebar links for the role of the currently logged in user +SideBarLinks() + +st.title(f"Welcome System Administrator, {st.session_state['first_name']}.") +st.write('') +st.write('') +st.write('### What would you like to do today?') + +if st.button('View Admin Dashboard', + type='primary', + use_container_width=True): + st.switch_page('pages/3001_Admin_Dashboard.py') + +if st.button('View and Moderate Flagged Posts', + type='primary', + use_container_width=True): + st.switch_page('pages/3002_Flagged_Posts.py') + +if st.button('Edit and Update Company Profiles', + type='primary', + use_container_width=True): + st.switch_page('pages/3003_Company_Profiles.py') + +if st.button('View and Categorize User Feedback', + type='primary', + use_container_width=True): + st.switch_page('pages/3004_User_Feedback.py') + +if st.button('View Analytics and Trends', + type='primary', + use_container_width=True): + st.switch_page('pages/3005_Analytics_and_Trends.py') + From 0039ba1ef93eee489e3dcf261077c3df3ecff0e9 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:13:16 -0500 Subject: [PATCH 10/75] update Home.py --- app/src/Home.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/Home.py b/app/src/Home.py index 01f167a44f..d2ceb760ae 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -42,7 +42,7 @@ # functionality, we put a button on the screen that the user # can click to MIMIC logging in as that mock user. -if st.button("Act as Sebastian, a Student Co Op Searcher", +if st.button("Act as Sebastian, a Student Co-Op Searcher", type = 'primary', use_container_width=True): # when user clicks the button, they are now considered authenticated @@ -71,7 +71,8 @@ st.session_state['authenticated'] = True st.session_state['role'] = 'administrator' st.session_state['first_name'] = 'SysAdmin' - st.switch_page('pages/20_Admin_Home.py') + logger.info("Logging in as System Administrator") + st.switch_page('pages/300_System_Administrator.py') if st.button('Act as Annalise, an Analyist of Site Performance', From f7b415e69ee2fa689a19e134931f2a3943935b44 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:16:17 -0500 Subject: [PATCH 11/75] update admin --- app/src/Home.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/Home.py b/app/src/Home.py index d2ceb760ae..ab44bc3071 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -72,7 +72,7 @@ st.session_state['role'] = 'administrator' st.session_state['first_name'] = 'SysAdmin' logger.info("Logging in as System Administrator") - st.switch_page('pages/300_System_Administrator.py') + st.switch_page('pages/300_System_Administrator_Home.py') if st.button('Act as Annalise, an Analyist of Site Performance', From e398f5f88cab2e0097bd58966cd52cced0fd647a Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:24:23 -0500 Subject: [PATCH 12/75] update nav.py --- app/src/modules/nav.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/modules/nav.py b/app/src/modules/nav.py index cb31d3bf67..327181105e 100644 --- a/app/src/modules/nav.py +++ b/app/src/modules/nav.py @@ -50,10 +50,7 @@ def ClassificationNav(): #### ------------------------ System Admin Role ------------------------ def AdminPageNav(): - st.sidebar.page_link("pages/20_Admin_Home.py", label="System Admin", icon="🖥️") - st.sidebar.page_link( - "pages/21_ML_Model_Mgmt.py", label="ML Model Management", icon="🏢" - ) + st.sidebar.page_link("pages/300_System_Administrator_Home.py", label="System Admin", icon="🖥️") # --------------------------------Links Function ----------------------------------------------- From 592f0fff261037c6d6d9ee609688e7acc8803483 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 02:06:11 -0500 Subject: [PATCH 13/75] update --- app/src/pages/3001_Admin_Dashboard.py | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/app/src/pages/3001_Admin_Dashboard.py b/app/src/pages/3001_Admin_Dashboard.py index e69de29bb2..94e25a4768 100644 --- a/app/src/pages/3001_Admin_Dashboard.py +++ b/app/src/pages/3001_Admin_Dashboard.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Find Company and Position Reviews') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file From 19c68c14b260043b520dfc9738c0c06e340d2a9b Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 02:11:30 -0500 Subject: [PATCH 14/75] add database with fake data --- database-files/CoopPlatform.sql | 505 ++++++++++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 database-files/CoopPlatform.sql diff --git a/database-files/CoopPlatform.sql b/database-files/CoopPlatform.sql new file mode 100644 index 0000000000..3cd8a7ed24 --- /dev/null +++ b/database-files/CoopPlatform.sql @@ -0,0 +1,505 @@ +-- Create the database +CREATE DATABASE IF NOT EXISTS CoopPlatform; + + +-- Use the newly created database +USE CoopPlatform; + + +-- Create User table +CREATE TABLE User ( + userID INT AUTO_INCREMENT PRIMARY KEY, + firstName VARCHAR(50), + lastName VARCHAR(50), + email VARCHAR(100) UNIQUE, + major VARCHAR(50), + skills TEXT, + interests TEXT, + isAdmin BOOLEAN DEFAULT FALSE, + isAnalyst BOOLEAN DEFAULT FALSE +); + +INSERT INTO User (firstName, lastName, email, major, skills, interests, isAdmin, isAnalyst) VALUES +('Alice', 'Smith', 'alice.smith@example.com', 'Computer Science', 'Java, Python', 'AI, Robotics', FALSE, TRUE), +('Bob', 'Johnson', 'bob.johnson@example.com', 'Mathematics', 'R, MATLAB', 'Statistics, Data Science', FALSE, TRUE), +('Charlie', 'Brown', 'charlie.brown@example.com', 'Physics', 'C++, Fortran', 'Quantum Mechanics, Astrophysics', FALSE, FALSE), +('Diana', 'Prince', 'diana.prince@example.com', 'Electrical Engineering', 'C, Embedded Systems', 'Renewable Energy, IoT', FALSE, FALSE), +('Ethan', 'Hunt', 'ethan.hunt@example.com', 'Cybersecurity', 'Networking, Ethical Hacking', 'Digital Security, Cryptography', FALSE, TRUE), +('Fiona', 'Gallagher', 'fiona.gallagher@example.com', 'Psychology', 'SPSS, Data Analysis', 'Behavioral Studies, Neuropsychology', FALSE, FALSE), +('George', 'Michaels', 'george.michaels@example.com', 'Business', 'Excel, SQL', 'Entrepreneurship, Management', FALSE, FALSE), +('Hannah', 'Montana', 'hannah.montana@example.com', 'Music', 'Composition, Audio Editing', 'Songwriting, Producing', FALSE, FALSE), +('Ian', 'Malcolm', 'ian.malcolm@example.com', 'Biology', 'Genetics, Bioinformatics', 'Evolution, Conservation', FALSE, TRUE), +('Julia', 'Roberts', 'julia.roberts@example.com', 'Drama', 'Acting, Directing', 'Theater, Film Studies', FALSE, FALSE), +('Kevin', 'Hart', 'kevin.hart@example.com', 'Performing Arts', 'Comedy, Storytelling', 'Improv, Stand-up', FALSE, FALSE), +('Laura', 'Croft', 'laura.croft@example.com', 'Archaeology', 'Field Research, Mapping', 'Ancient Civilizations, Exploration', FALSE, TRUE), +('Michael', 'Scott', 'michael.scott@example.com', 'Business Administration', 'Leadership, Communication', 'Sales, Marketing', TRUE, FALSE), +('Nancy', 'Drew', 'nancy.drew@example.com', 'Criminology', 'Investigation, Profiling', 'Mysteries, Forensics', FALSE, FALSE), +('Oliver', 'Queen', 'oliver.queen@example.com', 'Political Science', 'Policy Analysis, Strategy', 'Social Justice, Governance', FALSE, FALSE), +('Penelope', 'Garcia', 'penelope.garcia@example.com', 'Information Systems', 'Database Management, Programming', 'Technology, Cybersecurity', FALSE, TRUE), +('Quincy', 'Jones', 'quincy.jones@example.com', 'Music', 'Arranging, Producing', 'Jazz, Classical', FALSE, FALSE), +('Rachel', 'Green', 'rachel.green@example.com', 'Fashion Design', 'Sketching, Sewing', 'Trends, Styling', FALSE, FALSE), +('Steve', 'Jobs', 'steve.jobs@example.com', 'Product Design', 'Innovation, Prototyping', 'Technology, Design Thinking', FALSE, TRUE), +('Tracy', 'Morgan', 'tracy.morgan@example.com', 'Comedy Writing', 'Humor, Screenwriting', 'Sitcoms, Stand-up', FALSE, FALSE), +('Uma', 'Thurman', 'uma.thurman@example.com', 'Film Studies', 'Directing, Editing', 'Cinema, Storytelling', FALSE, FALSE), +('Victor', 'Frankenstein', 'victor.frankenstein@example.com', 'Biotechnology', 'CRISPR, Synthetic Biology', 'Genetic Engineering, Bioethics', FALSE, TRUE), +('Will', 'Smith', 'will.smith@example.com', 'Acting', 'Acting, Producing', 'Film, Music', FALSE, FALSE), +('Xander', 'Harris', 'xander.harris@example.com', 'History', 'Archival Research, Writing', 'Medieval History, Literature', FALSE, FALSE), +('Yara', 'Greyjoy', 'yara.greyjoy@example.com', 'Marine Biology', 'Oceanography, Diving', 'Marine Conservation, Ecology', FALSE, TRUE), +('Zara', 'Larsson', 'zara.larsson@example.com', 'Music Production', 'Singing, Mixing', 'Pop Music, Performance', FALSE, FALSE), +('Adam', 'West', 'adam.west@example.com', 'Theater', 'Acting, Public Speaking', 'Drama, Performance', FALSE, FALSE), +('Bella', 'Swan', 'bella.swan@example.com', 'Literature', 'Creative Writing, Editing', 'Romance, Fiction', FALSE, FALSE), +('Chris', 'Evans', 'chris.evans@example.com', 'Film Production', 'Editing, Cinematography', 'Action, Direction', FALSE, TRUE), +('Derek', 'Shepherd', 'derek.shepherd@example.com', 'Medicine', 'Surgery, Research', 'Neurosurgery, Health Care', FALSE, FALSE), +('Evelyn', 'Salt', 'evelyn.salt@example.com', 'International Relations', 'Negotiation, Strategy', 'Conflict Resolution, Diplomacy', FALSE, FALSE), +('Finn', 'Hudson', 'finn.hudson@example.com', 'Music Education', 'Choir, Performance', 'Teaching, Vocal Training', FALSE, FALSE), +('Grace', 'Hopper', 'grace.hopper@example.com', 'Computer Science', 'Programming, Algorithms', 'Innovation, Women in Tech', TRUE, TRUE), +('Harvey', 'Specter', 'harvey.specter@example.com', 'Law', 'Litigation, Negotiation', 'Corporate Law, Strategy', FALSE, FALSE); + + +-- Create Companies table +CREATE TABLE Companies ( + companyID INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(100), + description TEXT +); + +INSERT INTO Companies (name, description) VALUES +('TechNova Inc.', 'A leading company in AI and machine learning solutions.'), +('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.'), +('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.'), +('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.'), +('BrightFuture Education', 'Providing online and in-person educational programs worldwide.'), +('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.'), +('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.'), +('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.'), +('GlobalTech Solutions', 'Delivering IT consulting and software development services.'), +('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.'), +('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.'), +('FinPro Banking', 'A financial services firm offering innovative banking solutions.'), +('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.'), +('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.'), +('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.'), +('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.'), +('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.'), +('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.'), +('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.'), +('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.'), +('Visionary Designs', 'Offering innovative and stylish interior design services.'), +('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.'), +('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.'), +('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.'), +('DataPulse Analytics', 'Helping businesses harness big data for decision-making.'), +('GreenTech Farms', 'Implementing innovative vertical farming solutions.'), +('CloudNet Systems', 'Offering cloud computing and data storage services.'), +('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.'), +('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.'), +('QuantumLeap Solutions', 'Researching quantum computing and its applications.'); + + +-- Create Industries table +CREATE TABLE Industries ( + industryID INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(100) +); + +INSERT INTO Industries (name) VALUES +('Information Technology'), +('Healthcare'), +('Education'), +('Finance'), +('Automotive'), +('Biotechnology'), +('Aerospace'), +('Renewable Energy'), +('Construction'), +('Entertainment'), +('Robotics'), +('Logistics'), +('Cybersecurity'), +('Sports and Recreation'), +('Real Estate'), +('Food and Beverage'), +('Interior Design'), +('Pet Care'), +('Travel and Tourism'), +('Manufacturing'), +('Data Analytics'), +('Agriculture'), +('Cloud Computing'), +('Arts and Crafts'), +('E-commerce'), +('Quantum Computing'), +('Fashion and Apparel'), +('Gaming'), +('Pharmaceuticals'), +('Marine and Aquatic Technologies'); + +-- Create the relationship table for Industries and Companies +CREATE TABLE CompanyIndustry ( + companyID INT, + industryID INT, + PRIMARY KEY (companyID, industryID), + FOREIGN KEY (companyID) REFERENCES Companies(companyID), + FOREIGN KEY (industryID) REFERENCES Industries(industryID) +); + +INSERT INTO CompanyIndustry (companyID, industryID) VALUES +(1, 1), -- TechNova Inc. -> Information Technology +(1, 13), -- TechNova Inc. -> Cybersecurity +(2, 22), -- GreenFields Ltd. -> Agriculture +(2, 8), -- GreenFields Ltd. -> Renewable Energy +(3, 7), -- SkyHigh Aerospace -> Aerospace +(4, 8), -- EcoEnergy Co. -> Renewable Energy +(4, 21), -- EcoEnergy Co. -> Manufacturing +(5, 3), -- BrightFuture Education -> Education +(6, 2), -- HealthCore Pharmaceuticals -> Healthcare +(6, 30), -- HealthCore Pharmaceuticals -> Pharmaceuticals +(7, 9), -- UrbanBuilders LLC -> Construction +(8, 30), -- AquaLife Systems -> Marine and Aquatic Technologies +(9, 1), -- GlobalTech Solutions -> Information Technology +(10, 10), -- Stellar Entertainment -> Entertainment +(11, 12), -- NextGen Robotics -> Robotics +(11, 21), -- NextGen Robotics -> Manufacturing +(12, 4), -- FinPro Banking -> Finance +(13, 5), -- AutoFuture Ltd. -> Automotive +(13, 21), -- AutoFuture Ltd. -> Manufacturing +(14, 6), -- BioGenomics Inc. -> Biotechnology +(14, 30), -- BioGenomics Inc. -> Pharmaceuticals +(15, 12), -- BlueOcean Logistics -> Logistics +(16, 13), -- CyberShield Security -> Cybersecurity +(17, 14), -- Peak Performance Sports -> Sports and Recreation +(18, 9), -- EcoHomes Construction -> Construction +(18, 8), -- EcoHomes Construction -> Renewable Energy +(19, 1), -- VirtuMed Technologies -> Information Technology +(19, 3), -- VirtuMed Technologies -> Education +(20, 17), -- Gourmet World Foods -> Food and Beverage +(21, 10), -- Visionary Designs -> Interior Design +(22, 18), -- PetCare Innovations -> Pet Care +(23, 19), -- TravelSphere Ltd. -> Travel and Tourism +(24, 21), -- FusionTech Manufacturing -> Manufacturing +(25, 20), -- DataPulse Analytics -> Data Analytics +(26, 22), -- GreenTech Farms -> Agriculture +(27, 23), -- CloudNet Systems -> Cloud Computing +(28, 24), -- ArtisanCrafts Co. -> Arts and Crafts +(29, 25), -- BrightPath Logistics -> E-commerce +(30, 26); -- QuantumLeap Solutions -> Quantum Computing + + +-- Create Location table +CREATE TABLE Location ( + locationID INT AUTO_INCREMENT PRIMARY KEY, + companyID INT, + address TEXT, + city VARCHAR(100), + state_province VARCHAR(100), + country VARCHAR(100), + FOREIGN KEY (companyID) REFERENCES Companies(companyID) +); + +INSERT INTO Location (companyID, address, city, state_province, country) VALUES +(1, '123 Innovation Blvd', 'San Francisco', 'California', 'USA'), +(2, '456 Greenway Rd', 'Seattle', 'Washington', 'USA'), +(3, '789 SkyHigh Dr', 'Huntsville', 'Alabama', 'USA'), +(4, '321 Solar St', 'Austin', 'Texas', 'USA'), +(5, '654 Bright Ln', 'Boston', 'Massachusetts', 'USA'), +(6, '987 Pharma Ave', 'Cambridge', 'Massachusetts', 'USA'), +(7, '111 Builder Way', 'New York', 'New York', 'USA'), +(8, '222 Water Works', 'Miami', 'Florida', 'USA'), +(9, '333 Tech Plaza', 'San Jose', 'California', 'USA'), +(10, '444 Entertainment Row', 'Los Angeles', 'California', 'USA'), +(11, '555 Robotics St', 'Pittsburgh', 'Pennsylvania', 'USA'), +(12, '666 Finance Blvd', 'Chicago', 'Illinois', 'USA'), +(13, '777 Auto Ln', 'Detroit', 'Michigan', 'USA'), +(14, '888 BioTech Rd', 'San Diego', 'California', 'USA'), +(15, '999 Ocean Dr', 'Savannah', 'Georgia', 'USA'), +(16, '121 Cyber Ave', 'Austin', 'Texas', 'USA'), +(17, '131 Sports Way', 'Portland', 'Oregon', 'USA'), +(18, '141 Eco Homes Blvd', 'Denver', 'Colorado', 'USA'), +(19, '151 MedTech Dr', 'Houston', 'Texas', 'USA'), +(20, '161 Gourmet St', 'Paris', 'Île-de-France', 'France'), +(21, '171 Design Ln', 'Milan', 'Lombardy', 'Italy'), +(22, '181 PetCare Way', 'Sydney', 'New South Wales', 'Australia'), +(23, '191 Travel Blvd', 'London', 'England', 'United Kingdom'), +(24, '201 FusionTech Rd', 'Munich', 'Bavaria', 'Germany'), +(25, '211 DataPulse Ave', 'Toronto', 'Ontario', 'Canada'), +(26, '221 Green Farms Rd', 'Amsterdam', 'North Holland', 'Netherlands'), +(27, '231 CloudNet Dr', 'Dublin', 'Leinster', 'Ireland'), +(28, '241 Artisan Row', 'Kyoto', 'Kyoto Prefecture', 'Japan'), +(29, '251 BrightPath Blvd', 'Shanghai', 'Shanghai', 'China'), +(30, '261 Quantum Leap Way', 'Zurich', 'Zurich', 'Switzerland'), +(1, '271 Silicon Way', 'Palo Alto', 'California', 'USA'), +(12, '282 Green Circle', 'Vancouver', 'British Columbia', 'Canada'), +(23, '293 Spaceport Dr', 'Cape Canaveral', 'Florida', 'USA'), +(24, '304 Renewable St', 'Berlin', 'Berlin', 'Germany'), +(5, '315 BrightStar Rd', 'Oslo', 'Oslo', 'Norway'), +(6, '326 Pharma Labs', 'Hyderabad', 'Telangana', 'India'), +(27, '337 Builder Ln', 'Tokyo', 'Tokyo Prefecture', 'Japan'), +(18, '348 Aqua Center', 'Cape Town', 'Western Cape', 'South Africa'), +(19, '359 TechHub Blvd', 'Bangalore', 'Karnataka', 'India'), +(10, '370 Creative Row', 'Stockholm', 'Stockholm County', 'Sweden'), +(21, '381 Robotics Ave', 'Seoul', 'Seoul', 'South Korea'), +(30, '392 Financial Way', 'Zurich', 'Zurich', 'Switzerland'), +(23, '403 Auto Plaza', 'Stuttgart', 'Baden-Württemberg', 'Germany'), +(14, '414 Biotech Blvd', 'Tel Aviv', 'Tel Aviv District', 'Israel'), +(5, '425 Logistics Lane', 'Dubai', 'Dubai', 'United Arab Emirates'); + + +-- Create Role table +CREATE TABLE Role ( + roleID INT AUTO_INCREMENT PRIMARY KEY, + companyID INT, + locationID INT, + roleName VARCHAR(100), + description TEXT, + skillsRequired TEXT, + FOREIGN KEY (companyID) REFERENCES Companies(companyID), + FOREIGN KEY (locationID) REFERENCES Location(locationID) +); + +INSERT INTO Role (companyID, locationID, roleName, description, skillsRequired) VALUES +(1, 1, 'Machine Learning Engineer', 'Design and implement machine learning models for real-world applications.', 'Python, TensorFlow, Data Analysis'), +(2, 2, 'Sustainability Analyst', 'Analyze and optimize sustainable farming practices.', 'Data Analysis, Agricultural Science'), +(3, 3, 'Aerospace Engineer', 'Develop advanced spacecraft and satellite systems.', 'C++, Aerodynamics, CAD'), +(4, 4, 'Renewable Energy Consultant', 'Consult on renewable energy projects and strategies.', 'Project Management, Solar Technology'), +(5, 5, 'Educational Content Developer', 'Create engaging educational materials for online learning.', 'Curriculum Design, Content Writing'), +(6, 6, 'Clinical Research Scientist', 'Conduct research on pharmaceutical treatments and solutions.', 'Pharmacology, Research Methods'), +(7, 7, 'Architectural Designer', 'Design urban structures and smart city layouts.', 'AutoCAD, Urban Planning'), +(8, 8, 'Water Systems Engineer', 'Develop innovative water purification and desalination systems.', 'Hydraulics, System Design'), +(9, 9, 'Software Developer', 'Build scalable software solutions for clients.', 'Java, SQL, Cloud Platforms'), +(10, 10, 'Video Producer', 'Produce and manage video content for global distribution.', 'Adobe Premiere, Cinematography'), +(11, 11, 'Robotics Engineer', 'Develop robotics solutions for industrial applications.', 'Python, Robotics Frameworks'), +(12, 12, 'Financial Analyst', 'Analyze financial data to provide strategic advice.', 'Excel, Financial Modeling'), +(13, 13, 'Automotive Engineer', 'Design and test autonomous vehicle systems.', 'Matlab, Simulink, AI'), +(14, 14, 'Biotechnology Researcher', 'Conduct research in genetic engineering and biotechnology.', 'CRISPR, Lab Techniques'), +(15, 15, 'Logistics Manager', 'Oversee and optimize supply chain operations.', 'Supply Chain Management, SAP'), +(16, 16, 'Cybersecurity Specialist', 'Protect systems from cyber threats and vulnerabilities.', 'Penetration Testing, Network Security'), +(17, 17, 'Sports Equipment Designer', 'Design high-performance sports equipment.', 'Material Science, CAD'), +(18, 18, 'Eco-Friendly Construction Manager', 'Lead eco-friendly building projects.', 'Project Management, Green Building Standards'), +(19, 19, 'Virtual Reality Developer', 'Develop VR applications for medical training.', 'Unity, C#, 3D Modeling'), +(20, 20, 'Food Product Manager', 'Manage and oversee the development of gourmet food products.', 'Food Science, Marketing'), +(21, 21, 'Interior Designer', 'Create innovative and stylish interior designs.', 'Sketching, 3D Rendering'), +(22, 22, 'Veterinary Product Specialist', 'Develop and promote veterinary products.', 'Animal Science, Product Development'), +(23, 23, 'Tour Guide Manager', 'Coordinate and manage unique travel experiences.', 'Hospitality Management, Customer Service'), +(24, 24, 'Manufacturing Process Engineer', 'Optimize manufacturing processes and workflows.', 'Process Design, Lean Manufacturing'), +(25, 25, 'Data Scientist', 'Analyze big data for actionable insights.', 'Python, Machine Learning, Data Visualization'), +(26, 26, 'Agricultural Engineer', 'Implement innovative agricultural technologies.', 'Mechanical Engineering, Agricultural Systems'), +(27, 27, 'Cloud Infrastructure Engineer', 'Manage and deploy cloud-based solutions.', 'AWS, Kubernetes, Networking'), +(28, 28, 'Artisan Product Designer', 'Design and promote handcrafted artisan products.', 'Creativity, Marketing'), +(29, 29, 'E-commerce Operations Manager', 'Manage e-commerce logistics and operations.', 'Inventory Management, Analytics'), +(30, 30, 'Quantum Computing Researcher', 'Research and develop quantum computing applications.', 'Quantum Mechanics, Algorithms'); + + +-- Create Reviews table +CREATE TABLE Reviews ( + reviewID INT AUTO_INCREMENT PRIMARY KEY, + userID INT, + roleID INT, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + updatedAt DATETIME ON UPDATE CURRENT_TIMESTAMP, + publishedAt DATETIME, + reviewType VARCHAR(50), + heading VARCHAR(100), + content TEXT, + views INT DEFAULT 0, + likes INT DEFAULT 0, + isFlagged BOOLEAN DEFAULT FALSE, + FOREIGN KEY (userID) REFERENCES User(userID), + FOREIGN KEY (roleID) REFERENCES Role(roleID) +); + +INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES +(1, 1, '2024-01-01 10:00:00', 'Experience', 'Great Experience as an ML Engineer', 'I had a fantastic experience working as a Machine Learning Engineer at TechNova Inc. Learned a lot about AI.', 150, 35, FALSE), +(2, 2, '2024-01-05 15:30:00', 'Feedback', 'Improved Sustainability Practices', 'The company is making significant strides in sustainability, but communication needs improvement.', 100, 20, FALSE), +(3, 3, '2024-01-10 09:45:00', 'Review', 'Exciting Role in Aerospace', 'Working on cutting-edge technology was inspiring. Would recommend it to any aspiring engineer.', 200, 50, FALSE), +(4, 4, '2024-01-15 14:20:00', 'Insight', 'Great Opportunity in Renewable Energy', 'A rewarding experience with excellent leadership and vision.', 120, 25, FALSE), +(5, 5, '2024-01-20 11:10:00', 'Experience', 'Rewarding Work Environment', 'Collaborative culture and strong focus on education made my role enjoyable.', 90, 15, FALSE), +(6, 6, '2024-01-25 17:00:00', 'Feedback', 'Cutting-Edge Research', 'Involved in exciting research but workload was quite heavy.', 140, 30, FALSE), +(7, 7, '2024-02-01 08:00:00', 'Review', 'Urban Development at Its Best', 'Loved working on innovative projects for smart cities.', 85, 10, FALSE), +(8, 8, '2024-02-05 10:30:00', 'Insight', 'Advancing Water Purification', 'Meaningful work but limited opportunities for growth.', 70, 12, FALSE), +(9, 9, '2024-02-10 13:15:00', 'Experience', 'Dynamic Work Environment', 'Fast-paced and challenging, great place for software enthusiasts.', 180, 40, FALSE), +(10, 10, '2024-02-15 16:45:00', 'Feedback', 'Creative and Supportive', 'Perfect workplace for creative professionals.', 75, 18, FALSE), +(11, 11, '2024-02-20 19:20:00', 'Review', 'Robotics Projects Worth Pursuing', 'Exciting projects but management needs improvement.', 95, 20, FALSE), +(12, 12, '2024-02-25 07:30:00', 'Insight', 'Great Start for Financial Analysts', 'Supportive team and ample learning opportunities.', 105, 22, FALSE), +(13, 13, '2024-03-01 11:50:00', 'Experience', 'Innovative Role in Automotive', 'Hands-on experience with cutting-edge technologies.', 130, 35, FALSE), +(14, 14, '2024-03-05 09:40:00', 'Feedback', 'Inspiring Research Environment', 'Focus on innovation, but better work-life balance needed.', 165, 28, FALSE), +(15, 15, '2024-03-10 12:25:00', 'Review', 'Streamlined Logistics Management', 'Efficient processes and a dynamic team.', 80, 14, FALSE), +(16, 16, '2024-03-15 14:00:00', 'Insight', 'Top-notch Cybersecurity Expertise', 'Fantastic workplace for security professionals.', 200, 50, FALSE), +(17, 17, '2024-03-20 15:30:00', 'Experience', 'Challenging Sports Equipment Design', 'Opportunity to innovate, but tight deadlines.', 60, 10, FALSE), +(18, 18, '2024-03-25 16:45:00', 'Feedback', 'Sustainable and Collaborative', 'Loved the eco-friendly approach and teamwork.', 95, 25, FALSE), +(19, 19, '2024-03-30 10:10:00', 'Review', 'Immersive VR Development', 'Great exposure to VR development, but lacked mentorship.', 120, 18, FALSE), +(20, 20, '2024-04-01 13:00:00', 'Insight', 'Delicious Career Growth', 'Enjoyed working on gourmet food projects.', 80, 16, FALSE), +(21, 21, '2024-04-05 14:30:00', 'Experience', 'Creative Interior Design Projects', 'Amazing projects but needs better client communication.', 110, 20, FALSE), +(22, 22, '2024-04-10 09:15:00', 'Feedback', 'Innovative Pet Products', 'Great workplace with a fun and collaborative culture.', 90, 22, FALSE), +(23, 23, '2024-04-15 10:45:00', 'Review', 'Rewarding Travel Role', 'TravelSphere provides ample learning opportunities.', 115, 18, FALSE), +(24, 24, '2024-04-20 11:30:00', 'Insight', 'Streamlined Manufacturing Process', 'High-tech projects but long hours.', 130, 24, FALSE), +(25, 25, '2024-04-25 16:00:00', 'Experience', 'Data-Driven Insights', 'DataPulse offers cutting-edge analytics projects.', 170, 40, FALSE), +(26, 26, '2024-05-01 09:40:00', 'Feedback', 'Smart Agricultural Practices', 'Good place to grow for agricultural engineers.', 140, 35, FALSE), +(27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), +(28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), +(29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), +(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE); + + +-- Create Comments table +CREATE TABLE Comments ( + commentID INT AUTO_INCREMENT PRIMARY KEY, + reviewID INT, + userID INT, + parentCommentID INT DEFAULT NULL, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + updatedAt DATETIME ON UPDATE CURRENT_TIMESTAMP, + content TEXT, + likes INT DEFAULT 0, + isFlagged BOOLEAN DEFAULT FALSE, + FOREIGN KEY (reviewID) REFERENCES Reviews(reviewID), + FOREIGN KEY (userID) REFERENCES User(userID), + FOREIGN KEY (parentCommentID) REFERENCES Comments(commentID) +); + +INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagged) VALUES +(1, 2, NULL, 'This sounds like a fantastic experience! Thanks for sharing.', 10, FALSE), +(1, 3, 1, 'Absolutely agree! I had a similar experience.', 5, FALSE), +(2, 4, NULL, 'Do you think the communication issue is company-wide?', 8, FALSE), +(2, 1, 4, 'Yes, I think it varies by team, but it’s something to improve.', 6, FALSE), +(3, 5, NULL, 'Aerospace is such an exciting field. How was the workload?', 12, FALSE), +(4, 6, NULL, 'I’ve been considering applying here. Any tips for getting in?', 15, FALSE), +(4, 2, 6, 'Focus on renewable energy projects in your portfolio.', 7, FALSE), +(5, 7, NULL, 'I love collaborative environments. Sounds like a great role.', 4, FALSE), +(6, 8, NULL, 'Heavy workloads can be tough. Was the management supportive?', 9, FALSE), +(6, 9, 8, 'They were supportive but often stretched thin.', 3, FALSE), +(7, 10, NULL, 'Smart cities are the future. How innovative were the projects?', 13, FALSE), +(8, 11, NULL, 'What kind of growth opportunities were you hoping for?', 6, FALSE), +(8, 3, 11, 'Leadership roles or cross-functional projects.', 4, FALSE), +(9, 12, NULL, 'Tech companies often have dynamic environments. Did you feel valued?', 11, FALSE), +(10, 13, NULL, 'Supportive workplaces are so important for creatives.', 8, FALSE), +(11, 14, NULL, 'Robotics is fascinating! What kind of robots did you work on?', 14, FALSE), +(11, 15, 14, 'Mostly industrial robots for manufacturing.', 7, FALSE), +(12, 16, NULL, 'Finance is challenging. Did you have a good team?', 10, FALSE), +(13, 17, NULL, 'I’d love to work on autonomous vehicles. Any advice?', 18, FALSE), +(14, 18, NULL, 'How innovative was the genetic research you were involved in?', 20, FALSE), +(14, 19, 18, 'Very cutting-edge, especially in CRISPR technology.', 12, FALSE), +(15, 20, NULL, 'Efficient logistics management is key to success.', 9, FALSE), +(16, 21, NULL, 'What kind of tools were used for cybersecurity?', 11, FALSE), +(16, 22, 21, 'Mostly Splunk, Wireshark, and custom tools.', 5, FALSE), +(17, 23, NULL, 'Tight deadlines can be tough. How was the work-life balance?', 7, FALSE), +(18, 24, NULL, 'Eco-friendly construction is inspiring. What projects stood out?', 14, FALSE), +(19, 25, NULL, 'VR development is fascinating. What applications did you focus on?', 17, FALSE), +(19, 26, 25, 'Medical training simulations. Very impactful.', 10, FALSE), +(20, 27, NULL, 'Gourmet food development sounds interesting! How creative was it?', 8, FALSE), +(21, 28, NULL, 'Interior design is so rewarding. What was your favorite project?', 13, FALSE); + +-- Create Badges table +CREATE TABLE Badges ( + badgeID INT AUTO_INCREMENT PRIMARY KEY, + badgeName VARCHAR(50) +); + +INSERT INTO Badges (badgeName) VALUES +('Top Contributor'), +('Expert Reviewer'), +('Helpful Commenter'), +('Insightful Reviewer'), +('Early Adopter'), +('Collaboration Champion'), +('Creative Thinker'), +('Innovation Advocate'), +('Team Player'), +('Knowledge Sharer'), +('Problem Solver'), +('Critical Thinker'), +('Community Builder'), +('Leadership Star'), +('Data Enthusiast'); + + +-- Create the relationship table for User and Badges +CREATE TABLE UserBadges ( + userID INT, + badgeID INT, + PRIMARY KEY (userID, badgeID), + FOREIGN KEY (userID) REFERENCES User(userID), + FOREIGN KEY (badgeID) REFERENCES Badges(badgeID) +); + +INSERT INTO UserBadges (userID, badgeID) VALUES +(1, 1), -- User 1: Top Contributor +(1, 2), -- User 1: Expert Reviewer +(2, 3), -- User 2: Helpful Commenter +(2, 4), -- User 2: Insightful Reviewer +(3, 5), -- User 3: Early Adopter +(4, 6), -- User 4: Collaboration Champion +(4, 7), -- User 4: Creative Thinker +(5, 8), -- User 5: Innovation Advocate +(6, 9), -- User 6: Team Player +(6, 10), -- User 6: Knowledge Sharer +(7, 11), -- User 7: Problem Solver +(8, 12), -- User 8: Critical Thinker +(9, 13), -- User 9: Community Builder +(10, 14), -- User 10: Leadership Star +(11, 15), -- User 11: Data Enthusiast +(12, 1), -- User 12: Top Contributor +(13, 4), -- User 13: Insightful Reviewer +(14, 6), -- User 14: Collaboration Champion +(15, 7), -- User 15: Creative Thinker +(16, 8), -- User 16: Innovation Advocate +(17, 3), -- User 17: Helpful Commenter +(18, 10), -- User 18: Knowledge Sharer +(19, 11), -- User 19: Problem Solver +(20, 12), -- User 20: Critical Thinker +(21, 13), -- User 21: Community Builder +(22, 14), -- User 22: Leadership Star +(23, 15), -- User 23: Data Enthusiast +(24, 5), -- User 24: Early Adopter +(25, 9), -- User 25: Team Player +(26, 2); -- User 26: Expert Reviewer + + +-- Create Feedback table +CREATE TABLE Feedback ( + feedbackID INT AUTO_INCREMENT PRIMARY KEY, + userID INT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + header VARCHAR(100), + content TEXT, + FOREIGN KEY (userID) REFERENCES User(userID) +); + +INSERT INTO Feedback (userID, header, content) VALUES +(1, 'Platform Improvement Suggestion', 'It would be great to have a dark mode feature for the platform.'), +(2, 'Bug Report', 'I encountered an error when trying to submit my review.'), +(3, 'Feature Request', 'A section for trending roles and reviews would be very useful.'), +(4, 'Positive Experience', 'The platform is user-friendly and intuitive. Keep up the great work!'), +(5, 'Role Matching Feedback', 'Role recommendations based on my skills are very accurate.'), +(6, 'Data Visualization Suggestion', 'Adding charts for role trends and analytics would be helpful.'), +(7, 'User Profile Customization', 'I’d like more options to customize my profile page.'), +(8, 'Slow Loading Issue', 'The reviews page sometimes loads very slowly.'), +(9, 'Mobile App Suggestion', 'A dedicated mobile app would improve accessibility.'), +(10, 'Content Moderation Concern', 'Some comments seem inappropriate and should be flagged faster.'), +(11, 'Review Sorting', 'Adding filters for reviews by date or popularity would be helpful.'), +(12, 'Badge System Feedback', 'The badge system is great but could be expanded with more levels.'), +(13, 'Search Functionality', 'The search bar could use better predictive text features.'), +(14, 'Community Engagement', 'The platform could host live events to foster more engagement.'), +(15, 'Navigation Improvement', 'The navigation menu could be more streamlined for new users.'), +(16, 'Privacy Concerns', 'I’d like more clarity on how my data is being used.'), +(17, 'Content Quality', 'Some reviews lack depth and could benefit from a word minimum.'), +(18, 'Notification Settings', 'Customizing notifications would make the experience better.'), +(19, 'Integration Request', 'Integration with LinkedIn would be highly beneficial.'), +(20, 'Overall Feedback', 'This platform has a lot of potential and is already very useful.'), +(21, 'Search Filter Request', 'Filters for location-based role searches would be very helpful.'), +(22, 'Comment Editing Option', 'It would be great if users could edit their comments after posting.'), +(23, 'Collaboration Features', 'Adding group discussions for roles or industries would foster collaboration.'), +(24, 'Enhanced Analytics', 'Role analytics could include average salaries and career growth trends.'), +(25, 'Email Notification Issues', 'I am not receiving email notifications for new comments on my reviews.'), +(26, 'Review Draft Saving', 'The ability to save a review as a draft would be helpful.'), +(27, 'Expanded Industry List', 'The platform could include more industries to choose from.'), +(28, 'User Verification', 'Adding user verification would increase trust in the community.'), +(29, 'Role Comparison Tool', 'A feature to compare roles side-by-side would be useful.'), +(30, 'Feedback Acknowledgement', 'It would be nice to get updates on submitted feedback.'), +(1, 'Improved Role Details', 'Providing detailed role descriptions with responsibilities would be helpful.'), +(2, 'Live Chat Support', 'Adding a live chat feature for user support would be beneficial.'), +(3, 'More Badge Categories', 'The badge system could include categories for mentorship and learning.'), +(4, 'Mentorship Program', 'A mentorship program linking experienced users with newcomers would be valuable.'), +(5, 'Content Curation', 'Curating high-quality reviews or featuring top contributors could inspire others.'); + + + From 1bd85c0d596a3784bd5b6449e793eead42582dfe Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 12:28:49 -0500 Subject: [PATCH 15/75] Example user information inserted --- database-files/11_EXuserQueries.sql | 61 +++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 database-files/11_EXuserQueries.sql diff --git a/database-files/11_EXuserQueries.sql b/database-files/11_EXuserQueries.sql new file mode 100644 index 0000000000..ada3aa5f9b --- /dev/null +++ b/database-files/11_EXuserQueries.sql @@ -0,0 +1,61 @@ +-- only the examples that update or insert into tables +USE CoopPlatform; + +-- 1.6 Insert a recent interview experience. +INSERT INTO InterviewReports (roleID, userID, questions, timeline, tips) +VALUES (1, 123, 'What are your strengths?', 'Applied in August, interviewed in September', 'Focus on teamwork skills and problem-solving.'); + + +-- Persona 2: Riley Reviewer + + +-- 2.1 Submit detailed insights on a co-op experience. +INSERT INTO Reviews (roleID, userID, publishedAt, heading, content) +VALUES (1, 123, NOW(), 'Great Work Environment', 'Collaborative and inclusive environment with supportive management.'); + + +-- 2.2 Break down feedback into structured categories. +-- Note: Adjusted to match the schema +INSERT INTO Reviews (roleID, userID, publishedAt, heading, content) +VALUES (2, 124, NOW(), 'Fast-Paced and Challenging', 'Innovative culture but tough work-life balance during campaigns.'); + + +-- 2.3 Provide feedback on work-life balance. +UPDATE Reviews +SET content = CONCAT(content, ' Flexible hours but tight deadlines occasionally.') +WHERE reviewID = 5; + + +-- 2.4 Describe an interview experience. +INSERT INTO InterviewReports (roleID, userID, questions, timeline, tips) +VALUES (2, 124, 'Behavioral and technical questions', 'Interview took 2 weeks', 'Focus on leadership examples for behavioral questions.'); + + +-- 2.5 Update a review after receiving a full-time offer. +UPDATE Reviews +SET heading = 'Supportive Mentorship Opportunities', content = CONCAT(content, ' Expanded to include leadership roles.') +WHERE reviewID = 5; + + +-- 2.6 Reward user contributions with badges. +INSERT INTO UserBadges (userID, badgeID) +VALUES (124, (SELECT badgeID FROM Badges WHERE badgeName = 'Top Reviewer')); + + +-- Persona 3: Alex Admin + + +-- 3.2 Resolve disputes over flagged content. +UPDATE Reviews +SET isFlagged = FALSE +WHERE reviewID = 10; + + +-- 3.3 Update company profiles. +UPDATE Companies +SET description = 'Leading tech company specializing in AI and robotics' +WHERE companyID = 3; + + + +-- Persona 4: Annalise Analyst From e56f906364828ec093735425585f7140859e855b Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 13:05:25 -0500 Subject: [PATCH 16/75] Rename files in database-files --- ...2_CoopPlatform.sql => 11_CoopPlatform.sql} | 0 database-files/11_EXuserQueries.sql | 61 ------------------- 2 files changed, 61 deletions(-) rename database-files/{12_CoopPlatform.sql => 11_CoopPlatform.sql} (100%) delete mode 100644 database-files/11_EXuserQueries.sql diff --git a/database-files/12_CoopPlatform.sql b/database-files/11_CoopPlatform.sql similarity index 100% rename from database-files/12_CoopPlatform.sql rename to database-files/11_CoopPlatform.sql diff --git a/database-files/11_EXuserQueries.sql b/database-files/11_EXuserQueries.sql deleted file mode 100644 index ada3aa5f9b..0000000000 --- a/database-files/11_EXuserQueries.sql +++ /dev/null @@ -1,61 +0,0 @@ --- only the examples that update or insert into tables -USE CoopPlatform; - --- 1.6 Insert a recent interview experience. -INSERT INTO InterviewReports (roleID, userID, questions, timeline, tips) -VALUES (1, 123, 'What are your strengths?', 'Applied in August, interviewed in September', 'Focus on teamwork skills and problem-solving.'); - - --- Persona 2: Riley Reviewer - - --- 2.1 Submit detailed insights on a co-op experience. -INSERT INTO Reviews (roleID, userID, publishedAt, heading, content) -VALUES (1, 123, NOW(), 'Great Work Environment', 'Collaborative and inclusive environment with supportive management.'); - - --- 2.2 Break down feedback into structured categories. --- Note: Adjusted to match the schema -INSERT INTO Reviews (roleID, userID, publishedAt, heading, content) -VALUES (2, 124, NOW(), 'Fast-Paced and Challenging', 'Innovative culture but tough work-life balance during campaigns.'); - - --- 2.3 Provide feedback on work-life balance. -UPDATE Reviews -SET content = CONCAT(content, ' Flexible hours but tight deadlines occasionally.') -WHERE reviewID = 5; - - --- 2.4 Describe an interview experience. -INSERT INTO InterviewReports (roleID, userID, questions, timeline, tips) -VALUES (2, 124, 'Behavioral and technical questions', 'Interview took 2 weeks', 'Focus on leadership examples for behavioral questions.'); - - --- 2.5 Update a review after receiving a full-time offer. -UPDATE Reviews -SET heading = 'Supportive Mentorship Opportunities', content = CONCAT(content, ' Expanded to include leadership roles.') -WHERE reviewID = 5; - - --- 2.6 Reward user contributions with badges. -INSERT INTO UserBadges (userID, badgeID) -VALUES (124, (SELECT badgeID FROM Badges WHERE badgeName = 'Top Reviewer')); - - --- Persona 3: Alex Admin - - --- 3.2 Resolve disputes over flagged content. -UPDATE Reviews -SET isFlagged = FALSE -WHERE reviewID = 10; - - --- 3.3 Update company profiles. -UPDATE Companies -SET description = 'Leading tech company specializing in AI and robotics' -WHERE companyID = 3; - - - --- Persona 4: Annalise Analyst From b6d15ce00586fb9005341dd4bec596eedf02c342 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 13:25:25 -0500 Subject: [PATCH 17/75] Riley Reviewer My Reviews page with route to api working --- api/.env.template | 6 ---- api/backend/products/products_routes.py | 48 +++++++++++++++++-------- app/src/Home.py | 7 ++-- app/src/my_custom_database.db | 0 app/src/pages/2001_Review_Form.py | 41 +++++++++++++++++++++ app/src/pages/2002_My_Reviews.py | 24 +++++++++++++ app/src/pages/200_CoOp_Reviewer_Home.py | 34 ++++++++++++++++++ 7 files changed, 137 insertions(+), 23 deletions(-) delete mode 100644 api/.env.template create mode 100644 app/src/my_custom_database.db create mode 100644 app/src/pages/2001_Review_Form.py create mode 100644 app/src/pages/2002_My_Reviews.py create mode 100644 app/src/pages/200_CoOp_Reviewer_Home.py diff --git a/api/.env.template b/api/.env.template deleted file mode 100644 index b24b99326f..0000000000 --- a/api/.env.template +++ /dev/null @@ -1,6 +0,0 @@ -SECRET_KEY=someCrazyS3cR3T!Key.! -DB_USER=root -DB_HOST=db -DB_PORT=3306 -DB_NAME=northwind -MYSQL_ROOT_PASSWORD= diff --git a/api/backend/products/products_routes.py b/api/backend/products/products_routes.py index a3e596d0d3..f6ea305802 100644 --- a/api/backend/products/products_routes.py +++ b/api/backend/products/products_routes.py @@ -21,12 +21,22 @@ @products.route('/products', methods=['GET']) def get_products(): query = ''' - SELECT id, - product_code, - product_name, - list_price, - category - FROM products + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = ; ''' # get a cursor object from the database @@ -53,16 +63,26 @@ def get_products(): # notice that the route takes and then you see id # as a parameter to the function. This is one way to send # parameterized information into the route handler. -@products.route('/product/', methods=['GET']) +@products.route('/reviewsByUser/', methods=['GET']) def get_product_detail (id): - query = f'''SELECT id, - product_name, - description, - list_price, - category - FROM products - WHERE id = {str(id)} + query = f''' + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = {str(id)}; ''' # logging the query for debugging purposes. diff --git a/app/src/Home.py b/app/src/Home.py index ab44bc3071..6a57f04d70 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -61,9 +61,10 @@ type = 'primary', use_container_width=True): st.session_state['authenticated'] = True - st.session_state['role'] = 'usaid_worker' - st.session_state['first_name'] = 'Mohammad' - st.switch_page('pages/100_CoOp_Searcher_Home.py') + st.session_state['role'] = 'Co-Op reviewer' + st.session_state['id'] = '1' + st.session_state['first_name'] = 'Riley' + st.switch_page('pages/200_CoOp_Reviewer_Home.py') if st.button('Act as System Administrator', type = 'primary', diff --git a/app/src/my_custom_database.db b/app/src/my_custom_database.db new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/2001_Review_Form.py b/app/src/pages/2001_Review_Form.py new file mode 100644 index 0000000000..c02f6ec1a8 --- /dev/null +++ b/app/src/pages/2001_Review_Form.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Find Company and Position Reviews') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py new file mode 100644 index 0000000000..3c837cc264 --- /dev/null +++ b/app/src/pages/2002_My_Reviews.py @@ -0,0 +1,24 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks +import requests + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('My Reviews') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +results = requests.get(f'http://api:4000/p/reviewsByUser/{st.session_state["id"]}').json() +st.dataframe(results) + diff --git a/app/src/pages/200_CoOp_Reviewer_Home.py b/app/src/pages/200_CoOp_Reviewer_Home.py new file mode 100644 index 0000000000..cdef5a34f1 --- /dev/null +++ b/app/src/pages/200_CoOp_Reviewer_Home.py @@ -0,0 +1,34 @@ +import logging +logger = logging.getLogger(__name__) +import streamlit as st +from modules.nav import SideBarLinks + +st.set_page_config(layout = 'wide') + +# Show appropriate sidebar links for the role of the currently logged in user +SideBarLinks() + +st.title(f"Welcome Co-op searcher, {st.session_state['first_name']}.") +st.write('') +st.write('') +st.write('### What would you like to do today?') + +if st.button('Write a Review', + type='primary', + use_container_width=True): + st.switch_page('pages/2001_Review_Form.py') + +if st.button('View My Reviews', + type='primary', + use_container_width=True): + st.switch_page('pages/2002_My_Reviews.py') + +# if st.button('View Positions with Matching Skills', +# type='primary', +# use_container_width=True): +# st.switch_page('pages/1003_Skill_Matching.py') + +# if st.button('Enter My Interview Experiences', +# type='primary', +# use_container_width=True): +# st.switch_page('pages/1004_Enter_Interview_Info.py') From 8e4536b370ea599d09eb1304bda6833d456b8039 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 13:38:55 -0500 Subject: [PATCH 18/75] Changed name of products API route to reviews --- api/backend/rest_entry.py | 4 +- .../reviews_routes.py} | 16 +- api/backend/reviews/reviews_routes.py | 223 ++++++++++++++++++ app/src/pages/2002_My_Reviews.py | 2 +- 4 files changed, 234 insertions(+), 11 deletions(-) rename api/backend/{products/products_routes.py => reviews copy/reviews_routes.py} (94%) create mode 100644 api/backend/reviews/reviews_routes.py diff --git a/api/backend/rest_entry.py b/api/backend/rest_entry.py index d8d78502d9..293beb554e 100644 --- a/api/backend/rest_entry.py +++ b/api/backend/rest_entry.py @@ -2,7 +2,7 @@ from backend.db_connection import db from backend.customers.customer_routes import customers -from backend.products.products_routes import products +from backend.reviews.reviews_routes import reviews from backend.simple.simple_routes import simple_routes import os from dotenv import load_dotenv @@ -41,7 +41,7 @@ def create_app(): app.logger.info('current_app(): registering blueprints with Flask app object.') app.register_blueprint(simple_routes) app.register_blueprint(customers, url_prefix='/c') - app.register_blueprint(products, url_prefix='/p') + app.register_blueprint(reviews, url_prefix='/r') # Don't forget to return the app object return app diff --git a/api/backend/products/products_routes.py b/api/backend/reviews copy/reviews_routes.py similarity index 94% rename from api/backend/products/products_routes.py rename to api/backend/reviews copy/reviews_routes.py index f6ea305802..9fb00d3d23 100644 --- a/api/backend/products/products_routes.py +++ b/api/backend/reviews copy/reviews_routes.py @@ -13,12 +13,12 @@ #------------------------------------------------------------ # Create a new Blueprint object, which is a collection of # routes. -products = Blueprint('products', __name__) +reviews = Blueprint('reviews', __name__) #------------------------------------------------------------ # Get all the products from the database, package them up, # and return them to the client -@products.route('/products', methods=['GET']) +@reviews.route('/products', methods=['GET']) def get_products(): query = ''' SELECT @@ -63,7 +63,7 @@ def get_products(): # notice that the route takes and then you see id # as a parameter to the function. This is one way to send # parameterized information into the route handler. -@products.route('/reviewsByUser/', methods=['GET']) +@reviews.route('/reviewsByUser/', methods=['GET']) def get_product_detail (id): query = f''' @@ -107,7 +107,7 @@ def get_product_detail (id): # ------------------------------------------------------------ # Get the top 5 most expensive products from the database -@products.route('/mostExpensive') +@reviews.route('/mostExpensive') def get_most_pop_products(): query = ''' @@ -132,7 +132,7 @@ def get_most_pop_products(): # ------------------------------------------------------------ # Route to get the 10 most expensive items from the # database. -@products.route('/tenMostExpensive', methods=['GET']) +@reviews.route('/tenMostExpensive', methods=['GET']) def get_10_most_expensive_products(): query = ''' @@ -159,7 +159,7 @@ def get_10_most_expensive_products(): # This is a POST route to add a new product. # Remember, we are using POST routes to create new entries # in the database. -@products.route('/product', methods=['POST']) +@reviews.route('/product', methods=['POST']) def add_new_product(): # In a POST request, there is a @@ -200,7 +200,7 @@ def add_new_product(): # ------------------------------------------------------------ ### Get all product categories -@products.route('/categories', methods = ['GET']) +@reviews.route('/categories', methods = ['GET']) def get_all_categories(): query = ''' SELECT DISTINCT category AS label, category as value @@ -220,7 +220,7 @@ def get_all_categories(): # ------------------------------------------------------------ # This is a stubbed route to update a product in the catalog # The SQL query would be an UPDATE. -@products.route('/product', methods = ['PUT']) +@reviews.route('/product', methods = ['PUT']) def update_product(): product_info = request.json current_app.logger.info(product_info) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py new file mode 100644 index 0000000000..5cff5468c6 --- /dev/null +++ b/api/backend/reviews/reviews_routes.py @@ -0,0 +1,223 @@ +######################################################## +# Sample customers blueprint of endpoints +# Remove this file if you are not using it in your project +######################################################## + +from flask import Blueprint +from flask import request +from flask import jsonify +from flask import make_response +from flask import current_app +from backend.db_connection import db + +#------------------------------------------------------------ +# Create a new Blueprint object, which is a collection of +# routes. +reviews = Blueprint('reviews', __name__) + + +# ------------------------------------------------------------ +# get product information about a specific product +# notice that the route takes and then you see id +# as a parameter to the function. This is one way to send +# parameterized information into the route handler. +@reviews.route('/reviewsByUser/', methods=['GET']) +def get_product_detail (id): + + query = f''' + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = {str(id)}; + ''' + + # get the database connection, execute the query, and + # fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + + +#------------------------------------------------------------ +# Get all the products from the database, package them up, +# and return them to the client +@reviews.route('/products', methods=['GET']) +def get_products(): + query = ''' + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = ; + ''' + + # get a cursor object from the database + cursor = db.get_db().cursor() + + # use cursor to query the database for a list of products + cursor.execute(query) + + # fetch all the data from the cursor + # The cursor will return the data as a + # Python Dictionary + theData = cursor.fetchall() + + # Create a HTTP Response object and add results of the query to it + # after "jasonify"-ing it. + response = make_response(jsonify(theData)) + # set the proper HTTP Status code of 200 (meaning all good) + response.status_code = 200 + # send the response back to the client + return response + + + +# ------------------------------------------------------------ +# Get the top 5 most expensive products from the database +@reviews.route('/mostExpensive') +def get_most_pop_products(): + + query = ''' + SELECT product_code, + product_name, + list_price, + reorder_level + FROM products + ORDER BY list_price DESC + LIMIT 5 + ''' + + # Same process as handler above + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +# ------------------------------------------------------------ +# Route to get the 10 most expensive items from the +# database. +@reviews.route('/tenMostExpensive', methods=['GET']) +def get_10_most_expensive_products(): + + query = ''' + SELECT product_code, + product_name, + list_price, + reorder_level + FROM products + ORDER BY list_price DESC + LIMIT 10 + ''' + + # Same process as above + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + + +# ------------------------------------------------------------ +# This is a POST route to add a new product. +# Remember, we are using POST routes to create new entries +# in the database. +@reviews.route('/product', methods=['POST']) +def add_new_product(): + + # In a POST request, there is a + # collecting data from the request object + the_data = request.json + current_app.logger.info(the_data) + + #extracting the variable + name = the_data['product_name'] + description = the_data['product_description'] + price = the_data['product_price'] + category = the_data['product_category'] + + query = f''' + INSERT INTO products (product_name, + description, + category, + list_price) + VALUES ('{name}', '{description}', '{category}', {str(price)}) + ''' + # TODO: Make sure the version of the query above works properly + # Constructing the query + # query = 'insert into products (product_name, description, category, list_price) values ("' + # query += name + '", "' + # query += description + '", "' + # query += category + '", ' + # query += str(price) + ')' + current_app.logger.info(query) + + # executing and committing the insert statement + cursor = db.get_db().cursor() + cursor.execute(query) + db.get_db().commit() + + response = make_response("Successfully added product") + response.status_code = 200 + return response + +# ------------------------------------------------------------ +### Get all product categories +@reviews.route('/categories', methods = ['GET']) +def get_all_categories(): + query = ''' + SELECT DISTINCT category AS label, category as value + FROM products + WHERE category IS NOT NULL + ORDER BY category + ''' + + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +# ------------------------------------------------------------ +# This is a stubbed route to update a product in the catalog +# The SQL query would be an UPDATE. +@reviews.route('/product', methods = ['PUT']) +def update_product(): + product_info = request.json + current_app.logger.info(product_info) + + return "Success" \ No newline at end of file diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index 3c837cc264..4924391578 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -19,6 +19,6 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -results = requests.get(f'http://api:4000/p/reviewsByUser/{st.session_state["id"]}').json() +results = requests.get(f'http://api:4000/r/reviewsByUser/{st.session_state["id"]}').json() st.dataframe(results) From c8719b96676009af0e3c6649f2114d89663b0c4b Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:52:37 -0500 Subject: [PATCH 19/75] update admin subpage --- app/src/pages/3001_Admin_Dashboard.py | 2 +- app/src/pages/3002_Flagged_Posts.py | 41 ++++++++++++++++++++++ app/src/pages/3003_Company_Profiles.py | 41 ++++++++++++++++++++++ app/src/pages/3004_User_Feedback.py | 41 ++++++++++++++++++++++ app/src/pages/3005_Analytics_and_Trends.py | 41 ++++++++++++++++++++++ 5 files changed, 165 insertions(+), 1 deletion(-) diff --git a/app/src/pages/3001_Admin_Dashboard.py b/app/src/pages/3001_Admin_Dashboard.py index 94e25a4768..950a074139 100644 --- a/app/src/pages/3001_Admin_Dashboard.py +++ b/app/src/pages/3001_Admin_Dashboard.py @@ -13,7 +13,7 @@ SideBarLinks() # set the header of the page -st.header('Find Company and Position Reviews') +st.header('View Admin Dashboard') # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py index e69de29bb2..aa3d3b224d 100644 --- a/app/src/pages/3002_Flagged_Posts.py +++ b/app/src/pages/3002_Flagged_Posts.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View and Moderate Flagged Posts') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file diff --git a/app/src/pages/3003_Company_Profiles.py b/app/src/pages/3003_Company_Profiles.py index e69de29bb2..c74d80b638 100644 --- a/app/src/pages/3003_Company_Profiles.py +++ b/app/src/pages/3003_Company_Profiles.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Edit and Updata Company Files') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index e69de29bb2..14f41aacd1 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View and Categorize User Feedback') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file diff --git a/app/src/pages/3005_Analytics_and_Trends.py b/app/src/pages/3005_Analytics_and_Trends.py index e69de29bb2..f9e6cd55fc 100644 --- a/app/src/pages/3005_Analytics_and_Trends.py +++ b/app/src/pages/3005_Analytics_and_Trends.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View Analytics and Trends') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file From ec7e3b26b415d8a08675bbe6331b56716797cdad Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:39:40 -0500 Subject: [PATCH 20/75] conncet the database CoopPlatform --- api/backend/feedback/feedback_routes.py | 85 +++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 api/backend/feedback/feedback_routes.py diff --git a/api/backend/feedback/feedback_routes.py b/api/backend/feedback/feedback_routes.py new file mode 100644 index 0000000000..694751591b --- /dev/null +++ b/api/backend/feedback/feedback_routes.py @@ -0,0 +1,85 @@ +######################################################## +# Sample customers blueprint of endpoints +# Remove this file if you are not using it in your project +######################################################## +from flask import Blueprint +from flask import request +from flask import jsonify +from flask import make_response +from flask import current_app +from backend.db_connection import db +from backend.ml_models.model01 import predict + +#------------------------------------------------------------ +# Create a new Blueprint object, which is a collection of +# routes. +feedback = Blueprint('feedback', __name__) + + +#------------------------------------------------------------ +# Get all customers from the system +@feedback.route('/feedback', methods=['GET']) +def get_feedback(): + cursor = db.get_db().cursor() + cursor.execute(''' + SELECT userID, timestamp, header, content + FROM Feedback; + ''') + + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + +''' +#------------------------------------------------------------ +# Update customer info for customer with particular userID +# Notice the manner of constructing the query. +@customers.route('/customers', methods=['PUT']) +def update_customer(): + current_app.logger.info('PUT /customers route') + cust_info = request.json + cust_id = cust_info['id'] + first = cust_info['first_name'] + last = cust_info['last_name'] + company = cust_info['company'] + + query = 'UPDATE customers SET first_name = %s, last_name = %s, company = %s where id = %s' + data = (first, last, company, cust_id) + cursor = db.get_db().cursor() + r = cursor.execute(query, data) + db.get_db().commit() + return 'customer updated!' + +#------------------------------------------------------------ +# Get customer detail for customer with particular userID +# Notice the manner of constructing the query. +@customers.route('/customers/', methods=['GET']) +def get_customer(userID): + current_app.logger.info('GET /customers/ route') + cursor = db.get_db().cursor() + cursor.execute('SELECT id, first_name, last_name FROM customers WHERE id = {0}'.format(userID)) + + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + +#------------------------------------------------------------ +# Makes use of the very simple ML model in to predict a value +# and returns it to the user +@customers.route('/prediction//', methods=['GET']) +def predict_value(var01, var02): + current_app.logger.info(f'var01 = {var01}') + current_app.logger.info(f'var02 = {var02}') + + returnVal = predict(var01, var02) + return_dict = {'result': returnVal} + + the_response = make_response(jsonify(return_dict)) + the_response.status_code = 200 + the_response.mimetype = 'application/json' + return the_response +''' \ No newline at end of file From ee2a6e84ef309aea42f604dbf161698962d15aec Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:41:39 -0500 Subject: [PATCH 21/75] update database --- api/backend/rest_entry.py | 3 +- app/src/pages/3004_User_Feedback.py | 29 +++------ database-files/10_coopPlatformDB.sql | 2 - database-files/11_EXuserQueries.sql | 61 ------------------- ...pPlatform.sql => 12_CoopPlatform_Data.sql} | 2 +- 5 files changed, 10 insertions(+), 87 deletions(-) delete mode 100644 database-files/11_EXuserQueries.sql rename database-files/{12_CoopPlatform.sql => 12_CoopPlatform_Data.sql} (100%) diff --git a/api/backend/rest_entry.py b/api/backend/rest_entry.py index 293beb554e..f580a0bb68 100644 --- a/api/backend/rest_entry.py +++ b/api/backend/rest_entry.py @@ -4,6 +4,7 @@ from backend.customers.customer_routes import customers from backend.reviews.reviews_routes import reviews from backend.simple.simple_routes import simple_routes +from backend.feedback.feedback_routes import feedback import os from dotenv import load_dotenv @@ -42,7 +43,7 @@ def create_app(): app.register_blueprint(simple_routes) app.register_blueprint(customers, url_prefix='/c') app.register_blueprint(reviews, url_prefix='/r') - + app.register_blueprint(feedback, url_prefix='/f') # Don't forget to return the app object return app diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index 14f41aacd1..6b31cc9ed2 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -1,9 +1,9 @@ import logging logger = logging.getLogger(__name__) import pandas as pd +import requests import streamlit as st from streamlit_extras.app_logo import add_logo -import world_bank_data as wb import matplotlib.pyplot as plt import numpy as np import plotly.express as px @@ -18,24 +18,9 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) - -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) - - st.pyplot(test_plot) - - -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) \ No newline at end of file +# get the feedbacks +try: + feedback = requests.get("http://api:4000/f/feedback").json() + st.dataframe(feedback) +except: + st.write("Could not to conncet to database to get user feedback") diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index 2c258aaab0..1eda86984c 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -1,5 +1,3 @@ - - -- Create the database CREATE DATABASE IF NOT EXISTS CoopPlatform; diff --git a/database-files/11_EXuserQueries.sql b/database-files/11_EXuserQueries.sql deleted file mode 100644 index ada3aa5f9b..0000000000 --- a/database-files/11_EXuserQueries.sql +++ /dev/null @@ -1,61 +0,0 @@ --- only the examples that update or insert into tables -USE CoopPlatform; - --- 1.6 Insert a recent interview experience. -INSERT INTO InterviewReports (roleID, userID, questions, timeline, tips) -VALUES (1, 123, 'What are your strengths?', 'Applied in August, interviewed in September', 'Focus on teamwork skills and problem-solving.'); - - --- Persona 2: Riley Reviewer - - --- 2.1 Submit detailed insights on a co-op experience. -INSERT INTO Reviews (roleID, userID, publishedAt, heading, content) -VALUES (1, 123, NOW(), 'Great Work Environment', 'Collaborative and inclusive environment with supportive management.'); - - --- 2.2 Break down feedback into structured categories. --- Note: Adjusted to match the schema -INSERT INTO Reviews (roleID, userID, publishedAt, heading, content) -VALUES (2, 124, NOW(), 'Fast-Paced and Challenging', 'Innovative culture but tough work-life balance during campaigns.'); - - --- 2.3 Provide feedback on work-life balance. -UPDATE Reviews -SET content = CONCAT(content, ' Flexible hours but tight deadlines occasionally.') -WHERE reviewID = 5; - - --- 2.4 Describe an interview experience. -INSERT INTO InterviewReports (roleID, userID, questions, timeline, tips) -VALUES (2, 124, 'Behavioral and technical questions', 'Interview took 2 weeks', 'Focus on leadership examples for behavioral questions.'); - - --- 2.5 Update a review after receiving a full-time offer. -UPDATE Reviews -SET heading = 'Supportive Mentorship Opportunities', content = CONCAT(content, ' Expanded to include leadership roles.') -WHERE reviewID = 5; - - --- 2.6 Reward user contributions with badges. -INSERT INTO UserBadges (userID, badgeID) -VALUES (124, (SELECT badgeID FROM Badges WHERE badgeName = 'Top Reviewer')); - - --- Persona 3: Alex Admin - - --- 3.2 Resolve disputes over flagged content. -UPDATE Reviews -SET isFlagged = FALSE -WHERE reviewID = 10; - - --- 3.3 Update company profiles. -UPDATE Companies -SET description = 'Leading tech company specializing in AI and robotics' -WHERE companyID = 3; - - - --- Persona 4: Annalise Analyst diff --git a/database-files/12_CoopPlatform.sql b/database-files/12_CoopPlatform_Data.sql similarity index 100% rename from database-files/12_CoopPlatform.sql rename to database-files/12_CoopPlatform_Data.sql index b5f1581c96..2a558aef85 100644 --- a/database-files/12_CoopPlatform.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -1,4 +1,3 @@ - -- Use the newly created database USE CoopPlatform; @@ -384,3 +383,4 @@ INSERT INTO Feedback (userID, header, content) VALUES + From 9f083c57576c96087f7ee78588ed99a0c55b5f2a Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 15:53:51 -0500 Subject: [PATCH 22/75] merge main --- api/.env.template | 6 - api/backend/feedback/feedback_routes.py | 85 ++++ api/backend/rest_entry.py | 7 +- .../reviews_routes.py} | 62 ++- api/backend/reviews/reviews_routes.py | 223 ++++++++++ app/src/Home.py | 7 +- app/src/my_custom_database.db | 0 app/src/pages/2001_Review_Form.py | 41 ++ app/src/pages/2002_My_Reviews.py | 24 ++ app/src/pages/200_CoOp_Reviewer_Home.py | 34 ++ app/src/pages/3001_Admin_Dashboard.py | 2 +- app/src/pages/3002_Flagged_Posts.py | 41 ++ app/src/pages/3003_Company_Profiles.py | 41 ++ app/src/pages/3004_User_Feedback.py | 26 ++ app/src/pages/3005_Analytics_and_Trends.py | 41 ++ database-files/10_coopPlatformDB.sql | 2 - database-files/11_CoopPlatform.sql | 2 +- database-files/12_CoopPlatform_Data.sql | 386 ++++++++++++++++++ 18 files changed, 993 insertions(+), 37 deletions(-) delete mode 100644 api/.env.template create mode 100644 api/backend/feedback/feedback_routes.py rename api/backend/{products/products_routes.py => reviews copy/reviews_routes.py} (87%) create mode 100644 api/backend/reviews/reviews_routes.py create mode 100644 app/src/my_custom_database.db create mode 100644 app/src/pages/2001_Review_Form.py create mode 100644 app/src/pages/2002_My_Reviews.py create mode 100644 app/src/pages/200_CoOp_Reviewer_Home.py create mode 100644 database-files/12_CoopPlatform_Data.sql diff --git a/api/.env.template b/api/.env.template deleted file mode 100644 index b24b99326f..0000000000 --- a/api/.env.template +++ /dev/null @@ -1,6 +0,0 @@ -SECRET_KEY=someCrazyS3cR3T!Key.! -DB_USER=root -DB_HOST=db -DB_PORT=3306 -DB_NAME=northwind -MYSQL_ROOT_PASSWORD= diff --git a/api/backend/feedback/feedback_routes.py b/api/backend/feedback/feedback_routes.py new file mode 100644 index 0000000000..694751591b --- /dev/null +++ b/api/backend/feedback/feedback_routes.py @@ -0,0 +1,85 @@ +######################################################## +# Sample customers blueprint of endpoints +# Remove this file if you are not using it in your project +######################################################## +from flask import Blueprint +from flask import request +from flask import jsonify +from flask import make_response +from flask import current_app +from backend.db_connection import db +from backend.ml_models.model01 import predict + +#------------------------------------------------------------ +# Create a new Blueprint object, which is a collection of +# routes. +feedback = Blueprint('feedback', __name__) + + +#------------------------------------------------------------ +# Get all customers from the system +@feedback.route('/feedback', methods=['GET']) +def get_feedback(): + cursor = db.get_db().cursor() + cursor.execute(''' + SELECT userID, timestamp, header, content + FROM Feedback; + ''') + + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + +''' +#------------------------------------------------------------ +# Update customer info for customer with particular userID +# Notice the manner of constructing the query. +@customers.route('/customers', methods=['PUT']) +def update_customer(): + current_app.logger.info('PUT /customers route') + cust_info = request.json + cust_id = cust_info['id'] + first = cust_info['first_name'] + last = cust_info['last_name'] + company = cust_info['company'] + + query = 'UPDATE customers SET first_name = %s, last_name = %s, company = %s where id = %s' + data = (first, last, company, cust_id) + cursor = db.get_db().cursor() + r = cursor.execute(query, data) + db.get_db().commit() + return 'customer updated!' + +#------------------------------------------------------------ +# Get customer detail for customer with particular userID +# Notice the manner of constructing the query. +@customers.route('/customers/', methods=['GET']) +def get_customer(userID): + current_app.logger.info('GET /customers/ route') + cursor = db.get_db().cursor() + cursor.execute('SELECT id, first_name, last_name FROM customers WHERE id = {0}'.format(userID)) + + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + +#------------------------------------------------------------ +# Makes use of the very simple ML model in to predict a value +# and returns it to the user +@customers.route('/prediction//', methods=['GET']) +def predict_value(var01, var02): + current_app.logger.info(f'var01 = {var01}') + current_app.logger.info(f'var02 = {var02}') + + returnVal = predict(var01, var02) + return_dict = {'result': returnVal} + + the_response = make_response(jsonify(return_dict)) + the_response.status_code = 200 + the_response.mimetype = 'application/json' + return the_response +''' \ No newline at end of file diff --git a/api/backend/rest_entry.py b/api/backend/rest_entry.py index d8d78502d9..f580a0bb68 100644 --- a/api/backend/rest_entry.py +++ b/api/backend/rest_entry.py @@ -2,8 +2,9 @@ from backend.db_connection import db from backend.customers.customer_routes import customers -from backend.products.products_routes import products +from backend.reviews.reviews_routes import reviews from backend.simple.simple_routes import simple_routes +from backend.feedback.feedback_routes import feedback import os from dotenv import load_dotenv @@ -41,8 +42,8 @@ def create_app(): app.logger.info('current_app(): registering blueprints with Flask app object.') app.register_blueprint(simple_routes) app.register_blueprint(customers, url_prefix='/c') - app.register_blueprint(products, url_prefix='/p') - + app.register_blueprint(reviews, url_prefix='/r') + app.register_blueprint(feedback, url_prefix='/f') # Don't forget to return the app object return app diff --git a/api/backend/products/products_routes.py b/api/backend/reviews copy/reviews_routes.py similarity index 87% rename from api/backend/products/products_routes.py rename to api/backend/reviews copy/reviews_routes.py index a3e596d0d3..9fb00d3d23 100644 --- a/api/backend/products/products_routes.py +++ b/api/backend/reviews copy/reviews_routes.py @@ -13,20 +13,30 @@ #------------------------------------------------------------ # Create a new Blueprint object, which is a collection of # routes. -products = Blueprint('products', __name__) +reviews = Blueprint('reviews', __name__) #------------------------------------------------------------ # Get all the products from the database, package them up, # and return them to the client -@products.route('/products', methods=['GET']) +@reviews.route('/products', methods=['GET']) def get_products(): query = ''' - SELECT id, - product_code, - product_name, - list_price, - category - FROM products + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = ; ''' # get a cursor object from the database @@ -53,16 +63,26 @@ def get_products(): # notice that the route takes and then you see id # as a parameter to the function. This is one way to send # parameterized information into the route handler. -@products.route('/product/', methods=['GET']) +@reviews.route('/reviewsByUser/', methods=['GET']) def get_product_detail (id): - query = f'''SELECT id, - product_name, - description, - list_price, - category - FROM products - WHERE id = {str(id)} + query = f''' + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = {str(id)}; ''' # logging the query for debugging purposes. @@ -87,7 +107,7 @@ def get_product_detail (id): # ------------------------------------------------------------ # Get the top 5 most expensive products from the database -@products.route('/mostExpensive') +@reviews.route('/mostExpensive') def get_most_pop_products(): query = ''' @@ -112,7 +132,7 @@ def get_most_pop_products(): # ------------------------------------------------------------ # Route to get the 10 most expensive items from the # database. -@products.route('/tenMostExpensive', methods=['GET']) +@reviews.route('/tenMostExpensive', methods=['GET']) def get_10_most_expensive_products(): query = ''' @@ -139,7 +159,7 @@ def get_10_most_expensive_products(): # This is a POST route to add a new product. # Remember, we are using POST routes to create new entries # in the database. -@products.route('/product', methods=['POST']) +@reviews.route('/product', methods=['POST']) def add_new_product(): # In a POST request, there is a @@ -180,7 +200,7 @@ def add_new_product(): # ------------------------------------------------------------ ### Get all product categories -@products.route('/categories', methods = ['GET']) +@reviews.route('/categories', methods = ['GET']) def get_all_categories(): query = ''' SELECT DISTINCT category AS label, category as value @@ -200,7 +220,7 @@ def get_all_categories(): # ------------------------------------------------------------ # This is a stubbed route to update a product in the catalog # The SQL query would be an UPDATE. -@products.route('/product', methods = ['PUT']) +@reviews.route('/product', methods = ['PUT']) def update_product(): product_info = request.json current_app.logger.info(product_info) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py new file mode 100644 index 0000000000..5cff5468c6 --- /dev/null +++ b/api/backend/reviews/reviews_routes.py @@ -0,0 +1,223 @@ +######################################################## +# Sample customers blueprint of endpoints +# Remove this file if you are not using it in your project +######################################################## + +from flask import Blueprint +from flask import request +from flask import jsonify +from flask import make_response +from flask import current_app +from backend.db_connection import db + +#------------------------------------------------------------ +# Create a new Blueprint object, which is a collection of +# routes. +reviews = Blueprint('reviews', __name__) + + +# ------------------------------------------------------------ +# get product information about a specific product +# notice that the route takes and then you see id +# as a parameter to the function. This is one way to send +# parameterized information into the route handler. +@reviews.route('/reviewsByUser/', methods=['GET']) +def get_product_detail (id): + + query = f''' + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = {str(id)}; + ''' + + # get the database connection, execute the query, and + # fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + + +#------------------------------------------------------------ +# Get all the products from the database, package them up, +# and return them to the client +@reviews.route('/products', methods=['GET']) +def get_products(): + query = ''' + SELECT + r.reviewID, + r.roleID, + r.createdAt, + r.updatedAt, + r.publishedAt, + r.reviewType, + r.heading, + r.content, + r.views, + r.likes, + r.isFlagged +FROM + Reviews r +WHERE + r.userID = ; + ''' + + # get a cursor object from the database + cursor = db.get_db().cursor() + + # use cursor to query the database for a list of products + cursor.execute(query) + + # fetch all the data from the cursor + # The cursor will return the data as a + # Python Dictionary + theData = cursor.fetchall() + + # Create a HTTP Response object and add results of the query to it + # after "jasonify"-ing it. + response = make_response(jsonify(theData)) + # set the proper HTTP Status code of 200 (meaning all good) + response.status_code = 200 + # send the response back to the client + return response + + + +# ------------------------------------------------------------ +# Get the top 5 most expensive products from the database +@reviews.route('/mostExpensive') +def get_most_pop_products(): + + query = ''' + SELECT product_code, + product_name, + list_price, + reorder_level + FROM products + ORDER BY list_price DESC + LIMIT 5 + ''' + + # Same process as handler above + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +# ------------------------------------------------------------ +# Route to get the 10 most expensive items from the +# database. +@reviews.route('/tenMostExpensive', methods=['GET']) +def get_10_most_expensive_products(): + + query = ''' + SELECT product_code, + product_name, + list_price, + reorder_level + FROM products + ORDER BY list_price DESC + LIMIT 10 + ''' + + # Same process as above + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + + +# ------------------------------------------------------------ +# This is a POST route to add a new product. +# Remember, we are using POST routes to create new entries +# in the database. +@reviews.route('/product', methods=['POST']) +def add_new_product(): + + # In a POST request, there is a + # collecting data from the request object + the_data = request.json + current_app.logger.info(the_data) + + #extracting the variable + name = the_data['product_name'] + description = the_data['product_description'] + price = the_data['product_price'] + category = the_data['product_category'] + + query = f''' + INSERT INTO products (product_name, + description, + category, + list_price) + VALUES ('{name}', '{description}', '{category}', {str(price)}) + ''' + # TODO: Make sure the version of the query above works properly + # Constructing the query + # query = 'insert into products (product_name, description, category, list_price) values ("' + # query += name + '", "' + # query += description + '", "' + # query += category + '", ' + # query += str(price) + ')' + current_app.logger.info(query) + + # executing and committing the insert statement + cursor = db.get_db().cursor() + cursor.execute(query) + db.get_db().commit() + + response = make_response("Successfully added product") + response.status_code = 200 + return response + +# ------------------------------------------------------------ +### Get all product categories +@reviews.route('/categories', methods = ['GET']) +def get_all_categories(): + query = ''' + SELECT DISTINCT category AS label, category as value + FROM products + WHERE category IS NOT NULL + ORDER BY category + ''' + + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +# ------------------------------------------------------------ +# This is a stubbed route to update a product in the catalog +# The SQL query would be an UPDATE. +@reviews.route('/product', methods = ['PUT']) +def update_product(): + product_info = request.json + current_app.logger.info(product_info) + + return "Success" \ No newline at end of file diff --git a/app/src/Home.py b/app/src/Home.py index ab44bc3071..6a57f04d70 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -61,9 +61,10 @@ type = 'primary', use_container_width=True): st.session_state['authenticated'] = True - st.session_state['role'] = 'usaid_worker' - st.session_state['first_name'] = 'Mohammad' - st.switch_page('pages/100_CoOp_Searcher_Home.py') + st.session_state['role'] = 'Co-Op reviewer' + st.session_state['id'] = '1' + st.session_state['first_name'] = 'Riley' + st.switch_page('pages/200_CoOp_Reviewer_Home.py') if st.button('Act as System Administrator', type = 'primary', diff --git a/app/src/my_custom_database.db b/app/src/my_custom_database.db new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/2001_Review_Form.py b/app/src/pages/2001_Review_Form.py new file mode 100644 index 0000000000..c02f6ec1a8 --- /dev/null +++ b/app/src/pages/2001_Review_Form.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Find Company and Position Reviews') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py new file mode 100644 index 0000000000..4924391578 --- /dev/null +++ b/app/src/pages/2002_My_Reviews.py @@ -0,0 +1,24 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks +import requests + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('My Reviews') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +results = requests.get(f'http://api:4000/r/reviewsByUser/{st.session_state["id"]}').json() +st.dataframe(results) + diff --git a/app/src/pages/200_CoOp_Reviewer_Home.py b/app/src/pages/200_CoOp_Reviewer_Home.py new file mode 100644 index 0000000000..cdef5a34f1 --- /dev/null +++ b/app/src/pages/200_CoOp_Reviewer_Home.py @@ -0,0 +1,34 @@ +import logging +logger = logging.getLogger(__name__) +import streamlit as st +from modules.nav import SideBarLinks + +st.set_page_config(layout = 'wide') + +# Show appropriate sidebar links for the role of the currently logged in user +SideBarLinks() + +st.title(f"Welcome Co-op searcher, {st.session_state['first_name']}.") +st.write('') +st.write('') +st.write('### What would you like to do today?') + +if st.button('Write a Review', + type='primary', + use_container_width=True): + st.switch_page('pages/2001_Review_Form.py') + +if st.button('View My Reviews', + type='primary', + use_container_width=True): + st.switch_page('pages/2002_My_Reviews.py') + +# if st.button('View Positions with Matching Skills', +# type='primary', +# use_container_width=True): +# st.switch_page('pages/1003_Skill_Matching.py') + +# if st.button('Enter My Interview Experiences', +# type='primary', +# use_container_width=True): +# st.switch_page('pages/1004_Enter_Interview_Info.py') diff --git a/app/src/pages/3001_Admin_Dashboard.py b/app/src/pages/3001_Admin_Dashboard.py index 94e25a4768..950a074139 100644 --- a/app/src/pages/3001_Admin_Dashboard.py +++ b/app/src/pages/3001_Admin_Dashboard.py @@ -13,7 +13,7 @@ SideBarLinks() # set the header of the page -st.header('Find Company and Position Reviews') +st.header('View Admin Dashboard') # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py index e69de29bb2..aa3d3b224d 100644 --- a/app/src/pages/3002_Flagged_Posts.py +++ b/app/src/pages/3002_Flagged_Posts.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View and Moderate Flagged Posts') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file diff --git a/app/src/pages/3003_Company_Profiles.py b/app/src/pages/3003_Company_Profiles.py index e69de29bb2..c74d80b638 100644 --- a/app/src/pages/3003_Company_Profiles.py +++ b/app/src/pages/3003_Company_Profiles.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('Edit and Updata Company Files') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index e69de29bb2..6b31cc9ed2 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -0,0 +1,26 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import requests +import streamlit as st +from streamlit_extras.app_logo import add_logo +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View and Categorize User Feedback') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the feedbacks +try: + feedback = requests.get("http://api:4000/f/feedback").json() + st.dataframe(feedback) +except: + st.write("Could not to conncet to database to get user feedback") diff --git a/app/src/pages/3005_Analytics_and_Trends.py b/app/src/pages/3005_Analytics_and_Trends.py index e69de29bb2..f9e6cd55fc 100644 --- a/app/src/pages/3005_Analytics_and_Trends.py +++ b/app/src/pages/3005_Analytics_and_Trends.py @@ -0,0 +1,41 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import world_bank_data as wb +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View Analytics and Trends') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the countries from the world bank data +with st.echo(code_location='above'): + countries:pd.DataFrame = wb.get_countries() + + st.dataframe(countries) + +# the with statment shows the code for this block above it +with st.echo(code_location='above'): + arr = np.random.normal(1, 1, size=100) + test_plot, ax = plt.subplots() + ax.hist(arr, bins=20) + + st.pyplot(test_plot) + + +with st.echo(code_location='above'): + slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] + data_crosstab = pd.crosstab(slim_countries['region'], + slim_countries['incomeLevel'], + margins = False) + st.table(data_crosstab) \ No newline at end of file diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index 2c258aaab0..1eda86984c 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -1,5 +1,3 @@ - - -- Create the database CREATE DATABASE IF NOT EXISTS CoopPlatform; diff --git a/database-files/11_CoopPlatform.sql b/database-files/11_CoopPlatform.sql index b5f1581c96..2a558aef85 100644 --- a/database-files/11_CoopPlatform.sql +++ b/database-files/11_CoopPlatform.sql @@ -1,4 +1,3 @@ - -- Use the newly created database USE CoopPlatform; @@ -384,3 +383,4 @@ INSERT INTO Feedback (userID, header, content) VALUES + diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql new file mode 100644 index 0000000000..2a558aef85 --- /dev/null +++ b/database-files/12_CoopPlatform_Data.sql @@ -0,0 +1,386 @@ +-- Use the newly created database +USE CoopPlatform; + + +INSERT INTO User (firstName, lastName, email, major, skills, interests, isAdmin, isAnalyst) VALUES +('Alice', 'Smith', 'alice.smith@example.com', 'Computer Science', 'Java, Python', 'AI, Robotics', FALSE, TRUE), +('Bob', 'Johnson', 'bob.johnson@example.com', 'Mathematics', 'R, MATLAB', 'Statistics, Data Science', FALSE, TRUE), +('Charlie', 'Brown', 'charlie.brown@example.com', 'Physics', 'C++, Fortran', 'Quantum Mechanics, Astrophysics', FALSE, FALSE), +('Diana', 'Prince', 'diana.prince@example.com', 'Electrical Engineering', 'C, Embedded Systems', 'Renewable Energy, IoT', FALSE, FALSE), +('Ethan', 'Hunt', 'ethan.hunt@example.com', 'Cybersecurity', 'Networking, Ethical Hacking', 'Digital Security, Cryptography', FALSE, TRUE), +('Fiona', 'Gallagher', 'fiona.gallagher@example.com', 'Psychology', 'SPSS, Data Analysis', 'Behavioral Studies, Neuropsychology', FALSE, FALSE), +('George', 'Michaels', 'george.michaels@example.com', 'Business', 'Excel, SQL', 'Entrepreneurship, Management', FALSE, FALSE), +('Hannah', 'Montana', 'hannah.montana@example.com', 'Music', 'Composition, Audio Editing', 'Songwriting, Producing', FALSE, FALSE), +('Ian', 'Malcolm', 'ian.malcolm@example.com', 'Biology', 'Genetics, Bioinformatics', 'Evolution, Conservation', FALSE, TRUE), +('Julia', 'Roberts', 'julia.roberts@example.com', 'Drama', 'Acting, Directing', 'Theater, Film Studies', FALSE, FALSE), +('Kevin', 'Hart', 'kevin.hart@example.com', 'Performing Arts', 'Comedy, Storytelling', 'Improv, Stand-up', FALSE, FALSE), +('Laura', 'Croft', 'laura.croft@example.com', 'Archaeology', 'Field Research, Mapping', 'Ancient Civilizations, Exploration', FALSE, TRUE), +('Michael', 'Scott', 'michael.scott@example.com', 'Business Administration', 'Leadership, Communication', 'Sales, Marketing', TRUE, FALSE), +('Nancy', 'Drew', 'nancy.drew@example.com', 'Criminology', 'Investigation, Profiling', 'Mysteries, Forensics', FALSE, FALSE), +('Oliver', 'Queen', 'oliver.queen@example.com', 'Political Science', 'Policy Analysis, Strategy', 'Social Justice, Governance', FALSE, FALSE), +('Penelope', 'Garcia', 'penelope.garcia@example.com', 'Information Systems', 'Database Management, Programming', 'Technology, Cybersecurity', FALSE, TRUE), +('Quincy', 'Jones', 'quincy.jones@example.com', 'Music', 'Arranging, Producing', 'Jazz, Classical', FALSE, FALSE), +('Rachel', 'Green', 'rachel.green@example.com', 'Fashion Design', 'Sketching, Sewing', 'Trends, Styling', FALSE, FALSE), +('Steve', 'Jobs', 'steve.jobs@example.com', 'Product Design', 'Innovation, Prototyping', 'Technology, Design Thinking', FALSE, TRUE), +('Tracy', 'Morgan', 'tracy.morgan@example.com', 'Comedy Writing', 'Humor, Screenwriting', 'Sitcoms, Stand-up', FALSE, FALSE), +('Uma', 'Thurman', 'uma.thurman@example.com', 'Film Studies', 'Directing, Editing', 'Cinema, Storytelling', FALSE, FALSE), +('Victor', 'Frankenstein', 'victor.frankenstein@example.com', 'Biotechnology', 'CRISPR, Synthetic Biology', 'Genetic Engineering, Bioethics', FALSE, TRUE), +('Will', 'Smith', 'will.smith@example.com', 'Acting', 'Acting, Producing', 'Film, Music', FALSE, FALSE), +('Xander', 'Harris', 'xander.harris@example.com', 'History', 'Archival Research, Writing', 'Medieval History, Literature', FALSE, FALSE), +('Yara', 'Greyjoy', 'yara.greyjoy@example.com', 'Marine Biology', 'Oceanography, Diving', 'Marine Conservation, Ecology', FALSE, TRUE), +('Zara', 'Larsson', 'zara.larsson@example.com', 'Music Production', 'Singing, Mixing', 'Pop Music, Performance', FALSE, FALSE), +('Adam', 'West', 'adam.west@example.com', 'Theater', 'Acting, Public Speaking', 'Drama, Performance', FALSE, FALSE), +('Bella', 'Swan', 'bella.swan@example.com', 'Literature', 'Creative Writing, Editing', 'Romance, Fiction', FALSE, FALSE), +('Chris', 'Evans', 'chris.evans@example.com', 'Film Production', 'Editing, Cinematography', 'Action, Direction', FALSE, TRUE), +('Derek', 'Shepherd', 'derek.shepherd@example.com', 'Medicine', 'Surgery, Research', 'Neurosurgery, Health Care', FALSE, FALSE), +('Evelyn', 'Salt', 'evelyn.salt@example.com', 'International Relations', 'Negotiation, Strategy', 'Conflict Resolution, Diplomacy', FALSE, FALSE), +('Finn', 'Hudson', 'finn.hudson@example.com', 'Music Education', 'Choir, Performance', 'Teaching, Vocal Training', FALSE, FALSE), +('Grace', 'Hopper', 'grace.hopper@example.com', 'Computer Science', 'Programming, Algorithms', 'Innovation, Women in Tech', TRUE, TRUE), +('Harvey', 'Specter', 'harvey.specter@example.com', 'Law', 'Litigation, Negotiation', 'Corporate Law, Strategy', FALSE, FALSE); + +INSERT INTO Companies (name, description) VALUES +('TechNova Inc.', 'A leading company in AI and machine learning solutions.'), +('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.'), +('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.'), +('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.'), +('BrightFuture Education', 'Providing online and in-person educational programs worldwide.'), +('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.'), +('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.'), +('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.'), +('GlobalTech Solutions', 'Delivering IT consulting and software development services.'), +('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.'), +('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.'), +('FinPro Banking', 'A financial services firm offering innovative banking solutions.'), +('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.'), +('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.'), +('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.'), +('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.'), +('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.'), +('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.'), +('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.'), +('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.'), +('Visionary Designs', 'Offering innovative and stylish interior design services.'), +('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.'), +('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.'), +('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.'), +('DataPulse Analytics', 'Helping businesses harness big data for decision-making.'), +('GreenTech Farms', 'Implementing innovative vertical farming solutions.'), +('CloudNet Systems', 'Offering cloud computing and data storage services.'), +('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.'), +('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.'), +('QuantumLeap Solutions', 'Researching quantum computing and its applications.'); + + + + +INSERT INTO Industries (name) VALUES +('Information Technology'), +('Healthcare'), +('Education'), +('Finance'), +('Automotive'), +('Biotechnology'), +('Aerospace'), +('Renewable Energy'), +('Construction'), +('Entertainment'), +('Robotics'), +('Logistics'), +('Cybersecurity'), +('Sports and Recreation'), +('Real Estate'), +('Food and Beverage'), +('Interior Design'), +('Pet Care'), +('Travel and Tourism'), +('Manufacturing'), +('Data Analytics'), +('Agriculture'), +('Cloud Computing'), +('Arts and Crafts'), +('E-commerce'), +('Quantum Computing'), +('Fashion and Apparel'), +('Gaming'), +('Pharmaceuticals'), +('Marine and Aquatic Technologies'); + + +INSERT INTO CompanyIndustry (companyID, industryID) VALUES +(1, 1), -- TechNova Inc. -> Information Technology +(1, 13), -- TechNova Inc. -> Cybersecurity +(2, 22), -- GreenFields Ltd. -> Agriculture +(2, 8), -- GreenFields Ltd. -> Renewable Energy +(3, 7), -- SkyHigh Aerospace -> Aerospace +(4, 8), -- EcoEnergy Co. -> Renewable Energy +(4, 21), -- EcoEnergy Co. -> Manufacturing +(5, 3), -- BrightFuture Education -> Education +(6, 2), -- HealthCore Pharmaceuticals -> Healthcare +(6, 30), -- HealthCore Pharmaceuticals -> Pharmaceuticals +(7, 9), -- UrbanBuilders LLC -> Construction +(8, 30), -- AquaLife Systems -> Marine and Aquatic Technologies +(9, 1), -- GlobalTech Solutions -> Information Technology +(10, 10), -- Stellar Entertainment -> Entertainment +(11, 12), -- NextGen Robotics -> Robotics +(11, 21), -- NextGen Robotics -> Manufacturing +(12, 4), -- FinPro Banking -> Finance +(13, 5), -- AutoFuture Ltd. -> Automotive +(13, 21), -- AutoFuture Ltd. -> Manufacturing +(14, 6), -- BioGenomics Inc. -> Biotechnology +(14, 30), -- BioGenomics Inc. -> Pharmaceuticals +(15, 12), -- BlueOcean Logistics -> Logistics +(16, 13), -- CyberShield Security -> Cybersecurity +(17, 14), -- Peak Performance Sports -> Sports and Recreation +(18, 9), -- EcoHomes Construction -> Construction +(18, 8), -- EcoHomes Construction -> Renewable Energy +(19, 1), -- VirtuMed Technologies -> Information Technology +(19, 3), -- VirtuMed Technologies -> Education +(20, 17), -- Gourmet World Foods -> Food and Beverage +(21, 10), -- Visionary Designs -> Interior Design +(22, 18), -- PetCare Innovations -> Pet Care +(23, 19), -- TravelSphere Ltd. -> Travel and Tourism +(24, 21), -- FusionTech Manufacturing -> Manufacturing +(25, 20), -- DataPulse Analytics -> Data Analytics +(26, 22), -- GreenTech Farms -> Agriculture +(27, 23), -- CloudNet Systems -> Cloud Computing +(28, 24), -- ArtisanCrafts Co. -> Arts and Crafts +(29, 25), -- BrightPath Logistics -> E-commerce +(30, 26); -- QuantumLeap Solutions -> Quantum Computing + +INSERT INTO Location (companyID, address, city, state_province, country) VALUES +(1, '123 Innovation Blvd', 'San Francisco', 'California', 'USA'), +(2, '456 Greenway Rd', 'Seattle', 'Washington', 'USA'), +(3, '789 SkyHigh Dr', 'Huntsville', 'Alabama', 'USA'), +(4, '321 Solar St', 'Austin', 'Texas', 'USA'), +(5, '654 Bright Ln', 'Boston', 'Massachusetts', 'USA'), +(6, '987 Pharma Ave', 'Cambridge', 'Massachusetts', 'USA'), +(7, '111 Builder Way', 'New York', 'New York', 'USA'), +(8, '222 Water Works', 'Miami', 'Florida', 'USA'), +(9, '333 Tech Plaza', 'San Jose', 'California', 'USA'), +(10, '444 Entertainment Row', 'Los Angeles', 'California', 'USA'), +(11, '555 Robotics St', 'Pittsburgh', 'Pennsylvania', 'USA'), +(12, '666 Finance Blvd', 'Chicago', 'Illinois', 'USA'), +(13, '777 Auto Ln', 'Detroit', 'Michigan', 'USA'), +(14, '888 BioTech Rd', 'San Diego', 'California', 'USA'), +(15, '999 Ocean Dr', 'Savannah', 'Georgia', 'USA'), +(16, '121 Cyber Ave', 'Austin', 'Texas', 'USA'), +(17, '131 Sports Way', 'Portland', 'Oregon', 'USA'), +(18, '141 Eco Homes Blvd', 'Denver', 'Colorado', 'USA'), +(19, '151 MedTech Dr', 'Houston', 'Texas', 'USA'), +(20, '161 Gourmet St', 'Paris', 'Île-de-France', 'France'), +(21, '171 Design Ln', 'Milan', 'Lombardy', 'Italy'), +(22, '181 PetCare Way', 'Sydney', 'New South Wales', 'Australia'), +(23, '191 Travel Blvd', 'London', 'England', 'United Kingdom'), +(24, '201 FusionTech Rd', 'Munich', 'Bavaria', 'Germany'), +(25, '211 DataPulse Ave', 'Toronto', 'Ontario', 'Canada'), +(26, '221 Green Farms Rd', 'Amsterdam', 'North Holland', 'Netherlands'), +(27, '231 CloudNet Dr', 'Dublin', 'Leinster', 'Ireland'), +(28, '241 Artisan Row', 'Kyoto', 'Kyoto Prefecture', 'Japan'), +(29, '251 BrightPath Blvd', 'Shanghai', 'Shanghai', 'China'), +(30, '261 Quantum Leap Way', 'Zurich', 'Zurich', 'Switzerland'), +(1, '271 Silicon Way', 'Palo Alto', 'California', 'USA'), +(12, '282 Green Circle', 'Vancouver', 'British Columbia', 'Canada'), +(23, '293 Spaceport Dr', 'Cape Canaveral', 'Florida', 'USA'), +(24, '304 Renewable St', 'Berlin', 'Berlin', 'Germany'), +(5, '315 BrightStar Rd', 'Oslo', 'Oslo', 'Norway'), +(6, '326 Pharma Labs', 'Hyderabad', 'Telangana', 'India'), +(27, '337 Builder Ln', 'Tokyo', 'Tokyo Prefecture', 'Japan'), +(18, '348 Aqua Center', 'Cape Town', 'Western Cape', 'South Africa'), +(19, '359 TechHub Blvd', 'Bangalore', 'Karnataka', 'India'), +(10, '370 Creative Row', 'Stockholm', 'Stockholm County', 'Sweden'), +(21, '381 Robotics Ave', 'Seoul', 'Seoul', 'South Korea'), +(30, '392 Financial Way', 'Zurich', 'Zurich', 'Switzerland'), +(23, '403 Auto Plaza', 'Stuttgart', 'Baden-Württemberg', 'Germany'), +(14, '414 Biotech Blvd', 'Tel Aviv', 'Tel Aviv District', 'Israel'), +(5, '425 Logistics Lane', 'Dubai', 'Dubai', 'United Arab Emirates'); + +INSERT INTO Role (companyID, locationID, roleName, description, skillsRequired) VALUES +(1, 1, 'Machine Learning Engineer', 'Design and implement machine learning models for real-world applications.', 'Python, TensorFlow, Data Analysis'), +(2, 2, 'Sustainability Analyst', 'Analyze and optimize sustainable farming practices.', 'Data Analysis, Agricultural Science'), +(3, 3, 'Aerospace Engineer', 'Develop advanced spacecraft and satellite systems.', 'C++, Aerodynamics, CAD'), +(4, 4, 'Renewable Energy Consultant', 'Consult on renewable energy projects and strategies.', 'Project Management, Solar Technology'), +(5, 5, 'Educational Content Developer', 'Create engaging educational materials for online learning.', 'Curriculum Design, Content Writing'), +(6, 6, 'Clinical Research Scientist', 'Conduct research on pharmaceutical treatments and solutions.', 'Pharmacology, Research Methods'), +(7, 7, 'Architectural Designer', 'Design urban structures and smart city layouts.', 'AutoCAD, Urban Planning'), +(8, 8, 'Water Systems Engineer', 'Develop innovative water purification and desalination systems.', 'Hydraulics, System Design'), +(9, 9, 'Software Developer', 'Build scalable software solutions for clients.', 'Java, SQL, Cloud Platforms'), +(10, 10, 'Video Producer', 'Produce and manage video content for global distribution.', 'Adobe Premiere, Cinematography'), +(11, 11, 'Robotics Engineer', 'Develop robotics solutions for industrial applications.', 'Python, Robotics Frameworks'), +(12, 12, 'Financial Analyst', 'Analyze financial data to provide strategic advice.', 'Excel, Financial Modeling'), +(13, 13, 'Automotive Engineer', 'Design and test autonomous vehicle systems.', 'Matlab, Simulink, AI'), +(14, 14, 'Biotechnology Researcher', 'Conduct research in genetic engineering and biotechnology.', 'CRISPR, Lab Techniques'), +(15, 15, 'Logistics Manager', 'Oversee and optimize supply chain operations.', 'Supply Chain Management, SAP'), +(16, 16, 'Cybersecurity Specialist', 'Protect systems from cyber threats and vulnerabilities.', 'Penetration Testing, Network Security'), +(17, 17, 'Sports Equipment Designer', 'Design high-performance sports equipment.', 'Material Science, CAD'), +(18, 18, 'Eco-Friendly Construction Manager', 'Lead eco-friendly building projects.', 'Project Management, Green Building Standards'), +(19, 19, 'Virtual Reality Developer', 'Develop VR applications for medical training.', 'Unity, C#, 3D Modeling'), +(20, 20, 'Food Product Manager', 'Manage and oversee the development of gourmet food products.', 'Food Science, Marketing'), +(21, 21, 'Interior Designer', 'Create innovative and stylish interior designs.', 'Sketching, 3D Rendering'), +(22, 22, 'Veterinary Product Specialist', 'Develop and promote veterinary products.', 'Animal Science, Product Development'), +(23, 23, 'Tour Guide Manager', 'Coordinate and manage unique travel experiences.', 'Hospitality Management, Customer Service'), +(24, 24, 'Manufacturing Process Engineer', 'Optimize manufacturing processes and workflows.', 'Process Design, Lean Manufacturing'), +(25, 25, 'Data Scientist', 'Analyze big data for actionable insights.', 'Python, Machine Learning, Data Visualization'), +(26, 26, 'Agricultural Engineer', 'Implement innovative agricultural technologies.', 'Mechanical Engineering, Agricultural Systems'), +(27, 27, 'Cloud Infrastructure Engineer', 'Manage and deploy cloud-based solutions.', 'AWS, Kubernetes, Networking'), +(28, 28, 'Artisan Product Designer', 'Design and promote handcrafted artisan products.', 'Creativity, Marketing'), +(29, 29, 'E-commerce Operations Manager', 'Manage e-commerce logistics and operations.', 'Inventory Management, Analytics'), +(30, 30, 'Quantum Computing Researcher', 'Research and develop quantum computing applications.', 'Quantum Mechanics, Algorithms'); + +INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES +(1, 1, '2024-01-01 10:00:00', 'Experience', 'Great Experience as an ML Engineer', 'I had a fantastic experience working as a Machine Learning Engineer at TechNova Inc. Learned a lot about AI.', 150, 35, FALSE), +(2, 2, '2024-01-05 15:30:00', 'Feedback', 'Improved Sustainability Practices', 'The company is making significant strides in sustainability, but communication needs improvement.', 100, 20, FALSE), +(3, 3, '2024-01-10 09:45:00', 'Review', 'Exciting Role in Aerospace', 'Working on cutting-edge technology was inspiring. Would recommend it to any aspiring engineer.', 200, 50, FALSE), +(4, 4, '2024-01-15 14:20:00', 'Insight', 'Great Opportunity in Renewable Energy', 'A rewarding experience with excellent leadership and vision.', 120, 25, FALSE), +(5, 5, '2024-01-20 11:10:00', 'Experience', 'Rewarding Work Environment', 'Collaborative culture and strong focus on education made my role enjoyable.', 90, 15, FALSE), +(6, 6, '2024-01-25 17:00:00', 'Feedback', 'Cutting-Edge Research', 'Involved in exciting research but workload was quite heavy.', 140, 30, FALSE), +(7, 7, '2024-02-01 08:00:00', 'Review', 'Urban Development at Its Best', 'Loved working on innovative projects for smart cities.', 85, 10, FALSE), +(8, 8, '2024-02-05 10:30:00', 'Insight', 'Advancing Water Purification', 'Meaningful work but limited opportunities for growth.', 70, 12, FALSE), +(9, 9, '2024-02-10 13:15:00', 'Experience', 'Dynamic Work Environment', 'Fast-paced and challenging, great place for software enthusiasts.', 180, 40, FALSE), +(10, 10, '2024-02-15 16:45:00', 'Feedback', 'Creative and Supportive', 'Perfect workplace for creative professionals.', 75, 18, FALSE), +(11, 11, '2024-02-20 19:20:00', 'Review', 'Robotics Projects Worth Pursuing', 'Exciting projects but management needs improvement.', 95, 20, FALSE), +(12, 12, '2024-02-25 07:30:00', 'Insight', 'Great Start for Financial Analysts', 'Supportive team and ample learning opportunities.', 105, 22, FALSE), +(13, 13, '2024-03-01 11:50:00', 'Experience', 'Innovative Role in Automotive', 'Hands-on experience with cutting-edge technologies.', 130, 35, FALSE), +(14, 14, '2024-03-05 09:40:00', 'Feedback', 'Inspiring Research Environment', 'Focus on innovation, but better work-life balance needed.', 165, 28, FALSE), +(15, 15, '2024-03-10 12:25:00', 'Review', 'Streamlined Logistics Management', 'Efficient processes and a dynamic team.', 80, 14, FALSE), +(16, 16, '2024-03-15 14:00:00', 'Insight', 'Top-notch Cybersecurity Expertise', 'Fantastic workplace for security professionals.', 200, 50, FALSE), +(17, 17, '2024-03-20 15:30:00', 'Experience', 'Challenging Sports Equipment Design', 'Opportunity to innovate, but tight deadlines.', 60, 10, FALSE), +(18, 18, '2024-03-25 16:45:00', 'Feedback', 'Sustainable and Collaborative', 'Loved the eco-friendly approach and teamwork.', 95, 25, FALSE), +(19, 19, '2024-03-30 10:10:00', 'Review', 'Immersive VR Development', 'Great exposure to VR development, but lacked mentorship.', 120, 18, FALSE), +(20, 20, '2024-04-01 13:00:00', 'Insight', 'Delicious Career Growth', 'Enjoyed working on gourmet food projects.', 80, 16, FALSE), +(21, 21, '2024-04-05 14:30:00', 'Experience', 'Creative Interior Design Projects', 'Amazing projects but needs better client communication.', 110, 20, FALSE), +(22, 22, '2024-04-10 09:15:00', 'Feedback', 'Innovative Pet Products', 'Great workplace with a fun and collaborative culture.', 90, 22, FALSE), +(23, 23, '2024-04-15 10:45:00', 'Review', 'Rewarding Travel Role', 'TravelSphere provides ample learning opportunities.', 115, 18, FALSE), +(24, 24, '2024-04-20 11:30:00', 'Insight', 'Streamlined Manufacturing Process', 'High-tech projects but long hours.', 130, 24, FALSE), +(25, 25, '2024-04-25 16:00:00', 'Experience', 'Data-Driven Insights', 'DataPulse offers cutting-edge analytics projects.', 170, 40, FALSE), +(26, 26, '2024-05-01 09:40:00', 'Feedback', 'Smart Agricultural Practices', 'Good place to grow for agricultural engineers.', 140, 35, FALSE), +(27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), +(28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), +(29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), +(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE); + + +INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagged) VALUES +(1, 2, NULL, 'This sounds like a fantastic experience! Thanks for sharing.', 10, FALSE), +(1, 3, 1, 'Absolutely agree! I had a similar experience.', 5, FALSE), +(2, 4, NULL, 'Do you think the communication issue is company-wide?', 8, FALSE), +(2, 1, 4, 'Yes, I think it varies by team, but it’s something to improve.', 6, FALSE), +(3, 5, NULL, 'Aerospace is such an exciting field. How was the workload?', 12, FALSE), +(4, 6, NULL, 'I’ve been considering applying here. Any tips for getting in?', 15, FALSE), +(4, 2, 6, 'Focus on renewable energy projects in your portfolio.', 7, FALSE), +(5, 7, NULL, 'I love collaborative environments. Sounds like a great role.', 4, FALSE), +(6, 8, NULL, 'Heavy workloads can be tough. Was the management supportive?', 9, FALSE), +(6, 9, 8, 'They were supportive but often stretched thin.', 3, FALSE), +(7, 10, NULL, 'Smart cities are the future. How innovative were the projects?', 13, FALSE), +(8, 11, NULL, 'What kind of growth opportunities were you hoping for?', 6, FALSE), +(8, 3, 11, 'Leadership roles or cross-functional projects.', 4, FALSE), +(9, 12, NULL, 'Tech companies often have dynamic environments. Did you feel valued?', 11, FALSE), +(10, 13, NULL, 'Supportive workplaces are so important for creatives.', 8, FALSE), +(11, 14, NULL, 'Robotics is fascinating! What kind of robots did you work on?', 14, FALSE), +(11, 15, 14, 'Mostly industrial robots for manufacturing.', 7, FALSE), +(12, 16, NULL, 'Finance is challenging. Did you have a good team?', 10, FALSE), +(13, 17, NULL, 'I’d love to work on autonomous vehicles. Any advice?', 18, FALSE), +(14, 18, NULL, 'How innovative was the genetic research you were involved in?', 20, FALSE), +(14, 19, 18, 'Very cutting-edge, especially in CRISPR technology.', 12, FALSE), +(15, 20, NULL, 'Efficient logistics management is key to success.', 9, FALSE), +(16, 21, NULL, 'What kind of tools were used for cybersecurity?', 11, FALSE), +(16, 22, 21, 'Mostly Splunk, Wireshark, and custom tools.', 5, FALSE), +(17, 23, NULL, 'Tight deadlines can be tough. How was the work-life balance?', 7, FALSE), +(18, 24, NULL, 'Eco-friendly construction is inspiring. What projects stood out?', 14, FALSE), +(19, 25, NULL, 'VR development is fascinating. What applications did you focus on?', 17, FALSE), +(19, 26, 25, 'Medical training simulations. Very impactful.', 10, FALSE), +(20, 27, NULL, 'Gourmet food development sounds interesting! How creative was it?', 8, FALSE), +(21, 28, NULL, 'Interior design is so rewarding. What was your favorite project?', 13, FALSE); + + +INSERT INTO Badges (badgeName) VALUES +('Top Contributor'), +('Expert Reviewer'), +('Helpful Commenter'), +('Insightful Reviewer'), +('Early Adopter'), +('Collaboration Champion'), +('Creative Thinker'), +('Innovation Advocate'), +('Team Player'), +('Knowledge Sharer'), +('Problem Solver'), +('Critical Thinker'), +('Community Builder'), +('Leadership Star'), +('Data Enthusiast'); + + +INSERT INTO UserBadges (userID, badgeID) VALUES +(1, 1), -- User 1: Top Contributor +(1, 2), -- User 1: Expert Reviewer +(2, 3), -- User 2: Helpful Commenter +(2, 4), -- User 2: Insightful Reviewer +(3, 5), -- User 3: Early Adopter +(4, 6), -- User 4: Collaboration Champion +(4, 7), -- User 4: Creative Thinker +(5, 8), -- User 5: Innovation Advocate +(6, 9), -- User 6: Team Player +(6, 10), -- User 6: Knowledge Sharer +(7, 11), -- User 7: Problem Solver +(8, 12), -- User 8: Critical Thinker +(9, 13), -- User 9: Community Builder +(10, 14), -- User 10: Leadership Star +(11, 15), -- User 11: Data Enthusiast +(12, 1), -- User 12: Top Contributor +(13, 4), -- User 13: Insightful Reviewer +(14, 6), -- User 14: Collaboration Champion +(15, 7), -- User 15: Creative Thinker +(16, 8), -- User 16: Innovation Advocate +(17, 3), -- User 17: Helpful Commenter +(18, 10), -- User 18: Knowledge Sharer +(19, 11), -- User 19: Problem Solver +(20, 12), -- User 20: Critical Thinker +(21, 13), -- User 21: Community Builder +(22, 14), -- User 22: Leadership Star +(23, 15), -- User 23: Data Enthusiast +(24, 5), -- User 24: Early Adopter +(25, 9), -- User 25: Team Player +(26, 2); -- User 26: Expert Reviewer + + + +INSERT INTO Feedback (userID, header, content) VALUES +(1, 'Platform Improvement Suggestion', 'It would be great to have a dark mode feature for the platform.'), +(2, 'Bug Report', 'I encountered an error when trying to submit my review.'), +(3, 'Feature Request', 'A section for trending roles and reviews would be very useful.'), +(4, 'Positive Experience', 'The platform is user-friendly and intuitive. Keep up the great work!'), +(5, 'Role Matching Feedback', 'Role recommendations based on my skills are very accurate.'), +(6, 'Data Visualization Suggestion', 'Adding charts for role trends and analytics would be helpful.'), +(7, 'User Profile Customization', 'I’d like more options to customize my profile page.'), +(8, 'Slow Loading Issue', 'The reviews page sometimes loads very slowly.'), +(9, 'Mobile App Suggestion', 'A dedicated mobile app would improve accessibility.'), +(10, 'Content Moderation Concern', 'Some comments seem inappropriate and should be flagged faster.'), +(11, 'Review Sorting', 'Adding filters for reviews by date or popularity would be helpful.'), +(12, 'Badge System Feedback', 'The badge system is great but could be expanded with more levels.'), +(13, 'Search Functionality', 'The search bar could use better predictive text features.'), +(14, 'Community Engagement', 'The platform could host live events to foster more engagement.'), +(15, 'Navigation Improvement', 'The navigation menu could be more streamlined for new users.'), +(16, 'Privacy Concerns', 'I’d like more clarity on how my data is being used.'), +(17, 'Content Quality', 'Some reviews lack depth and could benefit from a word minimum.'), +(18, 'Notification Settings', 'Customizing notifications would make the experience better.'), +(19, 'Integration Request', 'Integration with LinkedIn would be highly beneficial.'), +(20, 'Overall Feedback', 'This platform has a lot of potential and is already very useful.'), +(21, 'Search Filter Request', 'Filters for location-based role searches would be very helpful.'), +(22, 'Comment Editing Option', 'It would be great if users could edit their comments after posting.'), +(23, 'Collaboration Features', 'Adding group discussions for roles or industries would foster collaboration.'), +(24, 'Enhanced Analytics', 'Role analytics could include average salaries and career growth trends.'), +(25, 'Email Notification Issues', 'I am not receiving email notifications for new comments on my reviews.'), +(26, 'Review Draft Saving', 'The ability to save a review as a draft would be helpful.'), +(27, 'Expanded Industry List', 'The platform could include more industries to choose from.'), +(28, 'User Verification', 'Adding user verification would increase trust in the community.'), +(29, 'Role Comparison Tool', 'A feature to compare roles side-by-side would be useful.'), +(30, 'Feedback Acknowledgement', 'It would be nice to get updates on submitted feedback.'), +(1, 'Improved Role Details', 'Providing detailed role descriptions with responsibilities would be helpful.'), +(2, 'Live Chat Support', 'Adding a live chat feature for user support would be beneficial.'), +(3, 'More Badge Categories', 'The badge system could include categories for mentorship and learning.'), +(4, 'Mentorship Program', 'A mentorship program linking experienced users with newcomers would be valuable.'), +(5, 'Content Curation', 'Curating high-quality reviews or featuring top contributors could inspire others.'); + + + + From 0f43406bdcb14b848fcb65a8baa77d2cd20b68e5 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:08:47 -0500 Subject: [PATCH 23/75] add feedback status --- api/backend/feedback/feedback_routes.py | 2 +- app/src/pages/3004_User_Feedback.py | 37 ++++++++++++ database-files/10_coopPlatformDB.sql | 1 + database-files/12_CoopPlatform_Data.sql | 77 +++++++++++++------------ 4 files changed, 80 insertions(+), 37 deletions(-) diff --git a/api/backend/feedback/feedback_routes.py b/api/backend/feedback/feedback_routes.py index 694751591b..f83b6a7f9c 100644 --- a/api/backend/feedback/feedback_routes.py +++ b/api/backend/feedback/feedback_routes.py @@ -22,7 +22,7 @@ def get_feedback(): cursor = db.get_db().cursor() cursor.execute(''' - SELECT userID, timestamp, header, content + SELECT userID, timestamp, header, content, status FROM Feedback; ''') diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index 6b31cc9ed2..59022ee33a 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -18,9 +18,46 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") + # get the feedbacks try: feedback = requests.get("http://api:4000/f/feedback").json() st.dataframe(feedback) except: st.write("Could not to conncet to database to get user feedback") +''' +# 初期データ(フィードバックのサンプルデータ) +feedback_data = [ + {"ID": 1, "Feedback": "Add dark mode feature", "Status": "Pending"}, + {"ID": 2, "Feedback": "Improve app performance", "Status": "Pending"}, + {"ID": 3, "Feedback": "Add more language support", "Status": "Pending"}, +] + +# データフレームとして管理 +feedback_df = pd.DataFrame(feedback_data) + +# Streamlitアプリ +st.title("ユーザーフィードバック管理インターフェース") + +# フィードバックテーブルを表示 +st.subheader("フィードバック一覧") +st.dataframe(feedback_df) + +# フィードバックの更新フォーム +st.subheader("フィードバックのステータスを更新") +selected_id = st.selectbox("フィードバックIDを選択", feedback_df["ID"]) +new_status = st.radio( + "新しいステータスを選択", + ["In Progress", "Implemented", "Rejected"], + index=0, +) + +if st.button("ステータスを更新"): + # 該当するフィードバックのステータスを更新 + feedback_df.loc[feedback_df["ID"] == selected_id, "Status"] = new_status + st.success(f"フィードバックID {selected_id} のステータスを '{new_status}' に更新しました!") + +# 更新後のフィードバックテーブルを表示 +st.subheader("更新後のフィードバック一覧") +st.dataframe(feedback_df) +''' diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index 1eda86984c..8d880e5f8c 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -130,6 +130,7 @@ CREATE TABLE IF NOT EXISTS Feedback ( timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, header VARCHAR(100), content TEXT, + status VARCHAR(100) DEFAULT 'In Progress', FOREIGN KEY (userID) REFERENCES User(userID) ); diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index 2a558aef85..77f52e6235 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -344,42 +344,47 @@ INSERT INTO UserBadges (userID, badgeID) VALUES -INSERT INTO Feedback (userID, header, content) VALUES -(1, 'Platform Improvement Suggestion', 'It would be great to have a dark mode feature for the platform.'), -(2, 'Bug Report', 'I encountered an error when trying to submit my review.'), -(3, 'Feature Request', 'A section for trending roles and reviews would be very useful.'), -(4, 'Positive Experience', 'The platform is user-friendly and intuitive. Keep up the great work!'), -(5, 'Role Matching Feedback', 'Role recommendations based on my skills are very accurate.'), -(6, 'Data Visualization Suggestion', 'Adding charts for role trends and analytics would be helpful.'), -(7, 'User Profile Customization', 'I’d like more options to customize my profile page.'), -(8, 'Slow Loading Issue', 'The reviews page sometimes loads very slowly.'), -(9, 'Mobile App Suggestion', 'A dedicated mobile app would improve accessibility.'), -(10, 'Content Moderation Concern', 'Some comments seem inappropriate and should be flagged faster.'), -(11, 'Review Sorting', 'Adding filters for reviews by date or popularity would be helpful.'), -(12, 'Badge System Feedback', 'The badge system is great but could be expanded with more levels.'), -(13, 'Search Functionality', 'The search bar could use better predictive text features.'), -(14, 'Community Engagement', 'The platform could host live events to foster more engagement.'), -(15, 'Navigation Improvement', 'The navigation menu could be more streamlined for new users.'), -(16, 'Privacy Concerns', 'I’d like more clarity on how my data is being used.'), -(17, 'Content Quality', 'Some reviews lack depth and could benefit from a word minimum.'), -(18, 'Notification Settings', 'Customizing notifications would make the experience better.'), -(19, 'Integration Request', 'Integration with LinkedIn would be highly beneficial.'), -(20, 'Overall Feedback', 'This platform has a lot of potential and is already very useful.'), -(21, 'Search Filter Request', 'Filters for location-based role searches would be very helpful.'), -(22, 'Comment Editing Option', 'It would be great if users could edit their comments after posting.'), -(23, 'Collaboration Features', 'Adding group discussions for roles or industries would foster collaboration.'), -(24, 'Enhanced Analytics', 'Role analytics could include average salaries and career growth trends.'), -(25, 'Email Notification Issues', 'I am not receiving email notifications for new comments on my reviews.'), -(26, 'Review Draft Saving', 'The ability to save a review as a draft would be helpful.'), -(27, 'Expanded Industry List', 'The platform could include more industries to choose from.'), -(28, 'User Verification', 'Adding user verification would increase trust in the community.'), -(29, 'Role Comparison Tool', 'A feature to compare roles side-by-side would be useful.'), -(30, 'Feedback Acknowledgement', 'It would be nice to get updates on submitted feedback.'), -(1, 'Improved Role Details', 'Providing detailed role descriptions with responsibilities would be helpful.'), -(2, 'Live Chat Support', 'Adding a live chat feature for user support would be beneficial.'), -(3, 'More Badge Categories', 'The badge system could include categories for mentorship and learning.'), -(4, 'Mentorship Program', 'A mentorship program linking experienced users with newcomers would be valuable.'), -(5, 'Content Curation', 'Curating high-quality reviews or featuring top contributors could inspire others.'); +INSERT INTO Feedback (userID, header, content, status) VALUES +(1, 'Great Service', 'I really appreciate the recent updates to the app.', 'In Progress'), +(2, 'Feature Request', 'Could you add a scheduling feature for tasks?', 'Implemented'), +(3, 'Bug Report', 'The app freezes when trying to generate a report.', 'In Progress'), +(4, 'Login Issue', 'Unable to reset my password using the forgot password option.', 'Rejected'), +(5, 'UI Feedback', 'The new layout is great, but the text is too small.', 'Implemented'), +(6, 'Performance Issue', 'The site becomes unresponsive during peak hours.', 'In Progress'), +(7, 'Dark Mode', 'Dark mode would improve usability at night.', 'Implemented'), +(8, 'Security Concern', 'Is there two-factor authentication available?', 'Rejected'), +(9, 'Account Feature', 'Can you provide an option to link multiple accounts?', 'In Progress'), +(10, 'Pricing Feedback', 'The pricing tiers seem unclear to new users.', 'Rejected'), +(11, 'New Feature', 'Adding analytics dashboards would be a great feature.', 'Implemented'), +(12, 'Mobile App Issue', 'The mobile app crashes when scrolling through large lists.', 'In Progress'), +(13, 'Positive Feedback', 'The team is doing a fantastic job with updates.', 'Implemented'), +(14, 'Bug in Search', 'The search function does not return relevant results.', 'In Progress'), +(15, 'User Permissions', 'Please allow admins to set custom permissions.', 'Implemented'), +(16, 'Customer Support', 'Your customer support resolved my issue quickly!', 'Rejected'), +(17, 'Feature Request', 'It would be great to have offline mode in the app.', 'Implemented'), +(18, 'Slow Loading', 'Pages take a long time to load on mobile devices.', 'In Progress'), +(19, 'API Enhancement', 'Can you add more filters to the API endpoints?', 'Rejected'), +(20, 'Email Notifications', 'The email notifications are inconsistent.', 'In Progress'), +(21, 'Dashboard Update', 'I like the new dashboard, but it feels a bit cluttered.', 'Implemented'), +(22, 'Integration Request', 'Can you integrate with XYZ service?', 'Rejected'), +(23, 'Navigation Issue', 'The navigation menu disappears on smaller screens.', 'In Progress'), +(24, 'Search Enhancement', 'Can you add autocomplete to the search bar?', 'Implemented'), +(25, 'Feature Idea', 'How about a collaborative editing feature?', 'In Progress'), +(26, 'UI Feedback', 'The color contrast is not accessible for all users.', 'Rejected'), +(27, 'Report Generation', 'Reports take too long to generate.', 'Implemented'), +(28, 'Settings Option', 'Allow users to export their settings as a file.', 'In Progress'), +(29, 'Appreciation', 'The recent updates have been excellent!', 'Implemented'), +(30, 'Feedback on Beta', 'The beta version is unstable on older devices.', 'Rejected'), +(1, 'Suggestion', 'Add a save as draft option for posts.', 'Implemented'), +(2, 'Account Settings', 'The account settings are difficult to navigate.', 'In Progress'), +(3, 'Feature Request', 'Include a timer for sessions.', 'Rejected'), +(4, 'UI Improvement', 'The text alignment on the settings page is off.', 'In Progress'), +(5, 'Server Downtime', 'The server goes down frequently in my region.', 'Implemented'), +(6, 'Password Management', 'Add a password strength indicator.', 'Rejected'), +(7, 'Onboarding', 'The onboarding process is not very user-friendly.', 'In Progress'), +(8, 'Localization', 'Can you add support for more languages?', 'Implemented'), +(9, 'Social Media', 'Integrate with popular social media platforms.', 'Rejected'), +(10, 'Billing System', 'The billing system has recurring issues.', 'In Progress'); From ea448c8e37bc0e97bba4130bd2198a348f6364bf Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 16:17:50 -0500 Subject: [PATCH 24/75] removed .env from git ignore --- .gitignore | 1 - api/.env | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 api/.env diff --git a/.gitignore b/.gitignore index 76db9a8b51..565b651700 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ secrets.toml __pycache__ secrets/ -.env .env.local \ No newline at end of file diff --git a/api/.env b/api/.env new file mode 100644 index 0000000000..fcb5a4bddb --- /dev/null +++ b/api/.env @@ -0,0 +1,6 @@ +SECRET_KEY=someCrazyS3cR3T!Key.! +DB_USER=root +DB_HOST=db +DB_PORT=3306 +DB_NAME=CoopPlatform +MYSQL_ROOT_PASSWORD=password From 52a2e8ba40b85bb60ed29f060620e3ab8c17be04 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:52:58 -0500 Subject: [PATCH 25/75] update feedback for admin --- api/backend/feedback/feedback_routes.py | 2 +- app/src/pages/3004_User_Feedback.py | 105 ++++++++++++------ ...form_Data.sql => 11_CoopPlatform_Data.sql} | 0 3 files changed, 75 insertions(+), 32 deletions(-) rename database-files/{12_CoopPlatform_Data.sql => 11_CoopPlatform_Data.sql} (100%) diff --git a/api/backend/feedback/feedback_routes.py b/api/backend/feedback/feedback_routes.py index f83b6a7f9c..cbb0b17c84 100644 --- a/api/backend/feedback/feedback_routes.py +++ b/api/backend/feedback/feedback_routes.py @@ -22,7 +22,7 @@ def get_feedback(): cursor = db.get_db().cursor() cursor.execute(''' - SELECT userID, timestamp, header, content, status + SELECT feedbackID, userID, timestamp, header, content, status FROM Feedback; ''') diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index 59022ee33a..395a54ca37 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -22,42 +22,85 @@ # get the feedbacks try: feedback = requests.get("http://api:4000/f/feedback").json() - st.dataframe(feedback) except: st.write("Could not to conncet to database to get user feedback") -''' -# 初期データ(フィードバックのサンプルデータ) -feedback_data = [ - {"ID": 1, "Feedback": "Add dark mode feature", "Status": "Pending"}, - {"ID": 2, "Feedback": "Improve app performance", "Status": "Pending"}, - {"ID": 3, "Feedback": "Add more language support", "Status": "Pending"}, -] - -# データフレームとして管理 -feedback_df = pd.DataFrame(feedback_data) - -# Streamlitアプリ -st.title("ユーザーフィードバック管理インターフェース") - -# フィードバックテーブルを表示 -st.subheader("フィードバック一覧") -st.dataframe(feedback_df) - -# フィードバックの更新フォーム -st.subheader("フィードバックのステータスを更新") -selected_id = st.selectbox("フィードバックIDを選択", feedback_df["ID"]) + +if "feedback_df" not in st.session_state: + st.session_state.feedback_df = pd.DataFrame(feedback) + +# title +st.title("User Feedback Management Interface") + +# Sort by status +st.subheader("Filter or Sort Feedback") +filter_option = st.radio( + "Select Filter or Sort Option", + ["Default", "Show Only In Progress", "Show Only Implemented", "Show Only Rejected", "Sort by FeedbackID"], + index=0, +) + +# Apply sorting or filtering +filtered_feedback_df = st.session_state.feedback_df.copy() + +if filter_option == "Show Only In Progress": + filtered_feedback_df = filtered_feedback_df[ + filtered_feedback_df["status"] == "In Progress" + ] +elif filter_option == "Show Only Implemented": + filtered_feedback_df = filtered_feedback_df[ + filtered_feedback_df["status"] == "Implemented" + ] +elif filter_option == "Show Only Rejected": + filtered_feedback_df = filtered_feedback_df[ + filtered_feedback_df["status"] == "Rejected" + ] +elif filter_option == "Sort by FeedbackID": + filtered_feedback_df = filtered_feedback_df.sort_values('feedbackID') + +else: + filtered_feedback_df["status"] = pd.Categorical( + filtered_feedback_df["status"], + categories=["In Progress", "Implemented", "Rejected"], + ordered=True, + ) + filtered_feedback_df = filtered_feedback_df.sort_values("status") + +# Select and rearrange columns +display_columns = ["status", "feedbackID", "userID", "timestamp", "header", "content"] +filtered_feedback_df = filtered_feedback_df[display_columns] + +filtered_feedback_df = filtered_feedback_df.reset_index(drop=True) + +# Display feedback table without index +st.subheader("Feedback List") +st.dataframe(filtered_feedback_df) + + + + + + +# Feedback update form +st.subheader("Update Feedback Status") +input_id = st.text_input("Enter Feedback ID") new_status = st.radio( - "新しいステータスを選択", + "Select New Status", ["In Progress", "Implemented", "Rejected"], index=0, ) -if st.button("ステータスを更新"): - # 該当するフィードバックのステータスを更新 - feedback_df.loc[feedback_df["ID"] == selected_id, "Status"] = new_status - st.success(f"フィードバックID {selected_id} のステータスを '{new_status}' に更新しました!") +if st.button("Update Status"): + # Validate ID + if input_id.isdigit() and int(input_id) in st.session_state.feedback_df["ID"].values: + selected_id = int(input_id) + # Update the status of the selected feedback + st.session_state.feedback_df.loc[ + st.session_state.feedback_df["ID"] == selected_id, "Status" + ] = new_status + st.success(f"Feedback ID {selected_id} status updated to '{new_status}'!") + else: + st.error("Please enter a valid Feedback ID.") -# 更新後のフィードバックテーブルを表示 -st.subheader("更新後のフィードバック一覧") -st.dataframe(feedback_df) -''' +# Display updated feedback table +st.subheader("Updated Feedback List") +st.dataframe(filtered_feedback_df) \ No newline at end of file diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/11_CoopPlatform_Data.sql similarity index 100% rename from database-files/12_CoopPlatform_Data.sql rename to database-files/11_CoopPlatform_Data.sql From 9354611948e1f8232b8beb5dda563457d21a65b8 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:22:42 -0500 Subject: [PATCH 26/75] complete feedback for admin --- api/.env | 2 +- api/backend/feedback/feedback_routes.py | 111 +++++++++++------------- api/backend/rest_entry.py | 2 +- app/src/pages/3004_User_Feedback.py | 34 ++++++-- 4 files changed, 81 insertions(+), 68 deletions(-) diff --git a/api/.env b/api/.env index fcb5a4bddb..dbe6e921f6 100644 --- a/api/.env +++ b/api/.env @@ -3,4 +3,4 @@ DB_USER=root DB_HOST=db DB_PORT=3306 DB_NAME=CoopPlatform -MYSQL_ROOT_PASSWORD=password +MYSQL_ROOT_PASSWORD=CoopCrazyS3 diff --git a/api/backend/feedback/feedback_routes.py b/api/backend/feedback/feedback_routes.py index cbb0b17c84..3b0929280b 100644 --- a/api/backend/feedback/feedback_routes.py +++ b/api/backend/feedback/feedback_routes.py @@ -17,69 +17,64 @@ #------------------------------------------------------------ -# Get all customers from the system +# Get all feedback from the system @feedback.route('/feedback', methods=['GET']) def get_feedback(): - cursor = db.get_db().cursor() - cursor.execute(''' - SELECT feedbackID, userID, timestamp, header, content, status - FROM Feedback; - ''') - - theData = cursor.fetchall() - - the_response = make_response(jsonify(theData)) - the_response.status_code = 200 - return the_response + try: + # カーソルの管理 + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT feedbackID, userID, timestamp, header, content, status + FROM Feedback; + ''') + theData = cursor.fetchall() -''' -#------------------------------------------------------------ -# Update customer info for customer with particular userID -# Notice the manner of constructing the query. -@customers.route('/customers', methods=['PUT']) -def update_customer(): - current_app.logger.info('PUT /customers route') - cust_info = request.json - cust_id = cust_info['id'] - first = cust_info['first_name'] - last = cust_info['last_name'] - company = cust_info['company'] + # レスポンスを返す + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response - query = 'UPDATE customers SET first_name = %s, last_name = %s, company = %s where id = %s' - data = (first, last, company, cust_id) - cursor = db.get_db().cursor() - r = cursor.execute(query, data) - db.get_db().commit() - return 'customer updated!' + except Exception as e: + current_app.logger.error(f"Error fetching feedback: {e}") + return {"error": "An error occurred while fetching feedback"}, 500 -#------------------------------------------------------------ -# Get customer detail for customer with particular userID -# Notice the manner of constructing the query. -@customers.route('/customers/', methods=['GET']) -def get_customer(userID): - current_app.logger.info('GET /customers/ route') - cursor = db.get_db().cursor() - cursor.execute('SELECT id, first_name, last_name FROM customers WHERE id = {0}'.format(userID)) - - theData = cursor.fetchall() - - the_response = make_response(jsonify(theData)) - the_response.status_code = 200 - return the_response -#------------------------------------------------------------ -# Makes use of the very simple ML model in to predict a value -# and returns it to the user -@customers.route('/prediction//', methods=['GET']) -def predict_value(var01, var02): - current_app.logger.info(f'var01 = {var01}') - current_app.logger.info(f'var02 = {var02}') +@feedback.route('/feedback', methods=['PUT']) +def update_status(): + current_app.logger.info('PUT /feedback route') + try: + feedback_info = request.json + + if 'feedbackID' not in feedback_info or 'status' not in feedback_info: + return {'error': 'Missing feedbackID or status'}, 400 + + status = feedback_info['status'] + feedback_id = feedback_info['feedbackID'] + + + query = ''' + UPDATE Feedback + SET status = %s + WHERE feedbackID = %s; + ''' + + + data = (status, feedback_id) - returnVal = predict(var01, var02) - return_dict = {'result': returnVal} + cursor = db.get_db().cursor() + cursor.execute(query, data) + db.get_db().commit() + + return {'message': 'Feedback status updated successfully'}, 200 + + except KeyError as e: + current_app.logger.error(f"Missing key in request JSON: {str(e)}") + return {'error': f'Missing key: {str(e)}'}, 400 + except Exception as e: + current_app.logger.error(f"Error updating feedback: {str(e)}") + return {'error': 'An error occurred while updating feedback status'}, 500 + finally: + if 'cursor' in locals() and cursor: + cursor.close() + - the_response = make_response(jsonify(return_dict)) - the_response.status_code = 200 - the_response.mimetype = 'application/json' - return the_response -''' \ No newline at end of file diff --git a/api/backend/rest_entry.py b/api/backend/rest_entry.py index f580a0bb68..54797162f5 100644 --- a/api/backend/rest_entry.py +++ b/api/backend/rest_entry.py @@ -43,7 +43,7 @@ def create_app(): app.register_blueprint(simple_routes) app.register_blueprint(customers, url_prefix='/c') app.register_blueprint(reviews, url_prefix='/r') - app.register_blueprint(feedback, url_prefix='/f') + app.register_blueprint(feedback, url_prefix='/f') # Don't forget to return the app object return app diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index 395a54ca37..ebbc972955 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -76,10 +76,6 @@ st.dataframe(filtered_feedback_df) - - - - # Feedback update form st.subheader("Update Feedback Status") input_id = st.text_input("Enter Feedback ID") @@ -89,18 +85,40 @@ index=0, ) + if st.button("Update Status"): # Validate ID - if input_id.isdigit() and int(input_id) in st.session_state.feedback_df["ID"].values: + if input_id.isdigit() and int(input_id) in st.session_state.feedback_df["feedbackID"].values: selected_id = int(input_id) - # Update the status of the selected feedback + + # Update the status of the selected feedback in the current dataframe st.session_state.feedback_df.loc[ - st.session_state.feedback_df["ID"] == selected_id, "Status" + st.session_state.feedback_df["feedbackID"] == selected_id, "status" ] = new_status st.success(f"Feedback ID {selected_id} status updated to '{new_status}'!") + + filtered_feedback_df.loc[filtered_feedback_df["feedbackID"] == int(input_id), "status"] = new_status + # Update the status of the selected feedback in the SQL database + + # data which is used for update + data = { + "feedbackID": selected_id, + "status": new_status + } + + response = requests.put("http://api:4000/f/feedback", json=data) + + # reflect the response + if response.status_code == 200: + print("Success:", response.json()) + else: + print("Error:", response.status_code, response.json()) + else: st.error("Please enter a valid Feedback ID.") # Display updated feedback table st.subheader("Updated Feedback List") -st.dataframe(filtered_feedback_df) \ No newline at end of file + +st.dataframe(filtered_feedback_df) + From ba9ca63ff20ea7baff9a495a5f9cd804d52950bd Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:17:17 -0500 Subject: [PATCH 27/75] update database --- api/backend/companies/companies_routes.py | 76 +++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 api/backend/companies/companies_routes.py diff --git a/api/backend/companies/companies_routes.py b/api/backend/companies/companies_routes.py new file mode 100644 index 0000000000..d6e8aa8fb6 --- /dev/null +++ b/api/backend/companies/companies_routes.py @@ -0,0 +1,76 @@ +######################################################## +# Companies blueprint of endpoints +######################################################## +from flask import Blueprint +from flask import request +from flask import jsonify +from flask import make_response +from flask import current_app +from backend.db_connection import db +from backend.ml_models.model01 import predict + +#------------------------------------------------------------ +# Create a new Blueprint object, which is a collection of +# routes. +companies = Blueprint('companies', __name__) + + +#------------------------------------------------------------ +# Get all feedback from the system +@companies.route('/companies', methods=['GET']) +def get_feedback(): + try: + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT feedbackID, userID, timestamp, header, content, status + FROM Feedback; + ''') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + + except Exception as e: + current_app.logger.error(f"Error fetching feedback: {e}") + return {"error": "An error occurred while fetching feedback"}, 500 + +''' +@feedback.route('/feedback', methods=['PUT']) +def update_status(): + current_app.logger.info('PUT /feedback route') + try: + feedback_info = request.json + + if 'feedbackID' not in feedback_info or 'status' not in feedback_info: + return {'error': 'Missing feedbackID or status'}, 400 + + status = feedback_info['status'] + feedback_id = feedback_info['feedbackID'] + + + query = + UPDATE Feedback + SET status = %s + WHERE feedbackID = %s; + + + + data = (status, feedback_id) + + cursor = db.get_db().cursor() + cursor.execute(query, data) + db.get_db().commit() + + return {'message': 'Feedback status updated successfully'}, 200 + + except KeyError as e: + current_app.logger.error(f"Missing key in request JSON: {str(e)}") + return {'error': f'Missing key: {str(e)}'}, 400 + except Exception as e: + current_app.logger.error(f"Error updating feedback: {str(e)}") + return {'error': 'An error occurred while updating feedback status'}, 500 + finally: + if 'cursor' in locals() and cursor: + cursor.close() +''' From 05a04854c54fa1804defa82457288950204f3d0e Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 19:31:01 -0500 Subject: [PATCH 28/75] Can write co op reviews now and it adds them to database --- api/backend/reviews/reviews_routes.py | 29 ++++++++++++++ app/src/pages/2001_Review_Form.py | 58 +++++++++++++++++---------- 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index 5cff5468c6..19539f9937 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -16,6 +16,35 @@ reviews = Blueprint('reviews', __name__) +@reviews.route('/addReview', methods=['POST']) +def add_review(): + review_data = request.json + try: + query = """ + INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) + """ + values = ( + review_data["userID"], + review_data["roleID"], + review_data["publishedAt"], + review_data["reviewType"], + review_data["heading"], + review_data["content"], + review_data["views"], + review_data["likes"], + review_data["isFlagged"] + ) + cursor = db.get_db().cursor() + cursor.execute(query, values) + db.get_db().commit() + return jsonify({"message": "Review added successfully!"}), 201 + except Exception as e: + error_message = str(e) + print("Error:", error_message) + print(traceback.format_exc()) + return jsonify({"error": error_message}), 500 + # ------------------------------------------------------------ # get product information about a specific product # notice that the route takes and then you see id diff --git a/app/src/pages/2001_Review_Form.py b/app/src/pages/2001_Review_Form.py index c02f6ec1a8..b5c413fd0c 100644 --- a/app/src/pages/2001_Review_Form.py +++ b/app/src/pages/2001_Review_Form.py @@ -8,34 +8,48 @@ import numpy as np import plotly.express as px from modules.nav import SideBarLinks +import requests # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() # set the header of the page -st.header('Find Company and Position Reviews') +st.header('Write A Co-Op Review') # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) - -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) - - st.pyplot(test_plot) - - -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) +st.header("Submit a New Review") + +# Create a form +with st.form("new_review_form"): + role_id = st.selectbox("Role", options=[1, 2, 3], format_func=lambda x: f"Role {x}") + review_type = st.selectbox("Review Type", options=["Experience", "Feedback", "Complaint"]) + heading = st.text_input("Heading", placeholder="Enter a brief heading for your review") + content = st.text_area("Content", placeholder="Write your review here...") + published_at = st.date_input("Published At") + + # Form submit button + submitted = st.form_submit_button("Submit") + +if submitted: + # Step 2: Prepare the data + new_review = { + "userID": st.session_state["id"], # Assuming the user's ID is stored in session_state + "roleID": role_id, + "publishedAt": published_at.isoformat(), # Convert to ISO format + "reviewType": review_type, + "heading": heading, + "content": content, + "views": 0, # Default value + "likes": 0, # Default value + "isFlagged": False # Default value + } + + # Step 3: Send the data to the API + try: + response = requests.post("http://api:4000/r/addReview", json=new_review) + response.raise_for_status() + st.success("Review submitted successfully!") + except requests.exceptions.RequestException as e: + st.error(f"An error occurred: {e}") From 45799c341295013183c67fdb51aea275e5b1e40d Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 20:50:09 -0500 Subject: [PATCH 29/75] update route company --- api/backend/companies/companies_routes.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/api/backend/companies/companies_routes.py b/api/backend/companies/companies_routes.py index d6e8aa8fb6..10ea780acc 100644 --- a/api/backend/companies/companies_routes.py +++ b/api/backend/companies/companies_routes.py @@ -22,8 +22,13 @@ def get_feedback(): try: with db.get_db().cursor() as cursor: cursor.execute(''' - SELECT feedbackID, userID, timestamp, header, content, status - FROM Feedback; + SELECT C.name, C.description, C.updatedAT, I.name, L.address, L.city, L.state_province, L.country, R.roleName, R.description, R.skillsRequired + FROM Companies C JOIN Location L + ON C.companyID = L.companyID JOIN CompanyIndustry CI + ON CI.companyID = C.companyID JOIN Industries I + ON I.industryID = CI.industryID JOIN Role R + ON R.companyID = C.companyID + ORDER BY C.name ASC; ''') theData = cursor.fetchall() @@ -32,8 +37,8 @@ def get_feedback(): return the_response except Exception as e: - current_app.logger.error(f"Error fetching feedback: {e}") - return {"error": "An error occurred while fetching feedback"}, 500 + current_app.logger.error(f"Error fetching companies: {e}") + return {"error": "An error occurred while fetching companies"}, 500 ''' @feedback.route('/feedback', methods=['PUT']) From 01c060e53694cecccf024fa8461046e7abd41900 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 20:51:11 -0500 Subject: [PATCH 30/75] update company for admin --- api/backend/feedback/feedback_routes.py | 5 +- api/backend/rest_entry.py | 6 +- app/src/pages/3003_Company_Profiles.py | 106 ++++++++++++++++++++---- database-files/10_coopPlatformDB.sql | 4 +- database-files/11_CoopPlatform_Data.sql | 62 +++++++------- 5 files changed, 126 insertions(+), 57 deletions(-) diff --git a/api/backend/feedback/feedback_routes.py b/api/backend/feedback/feedback_routes.py index 3b0929280b..c102e9acb6 100644 --- a/api/backend/feedback/feedback_routes.py +++ b/api/backend/feedback/feedback_routes.py @@ -1,6 +1,5 @@ ######################################################## -# Sample customers blueprint of endpoints -# Remove this file if you are not using it in your project +# Feedback blueprint of endpoints ######################################################## from flask import Blueprint from flask import request @@ -21,7 +20,6 @@ @feedback.route('/feedback', methods=['GET']) def get_feedback(): try: - # カーソルの管理 with db.get_db().cursor() as cursor: cursor.execute(''' SELECT feedbackID, userID, timestamp, header, content, status @@ -29,7 +27,6 @@ def get_feedback(): ''') theData = cursor.fetchall() - # レスポンスを返す the_response = make_response(jsonify(theData)) the_response.status_code = 200 return the_response diff --git a/api/backend/rest_entry.py b/api/backend/rest_entry.py index 54797162f5..0d0dc653ed 100644 --- a/api/backend/rest_entry.py +++ b/api/backend/rest_entry.py @@ -1,9 +1,9 @@ from flask import Flask from backend.db_connection import db -from backend.customers.customer_routes import customers from backend.reviews.reviews_routes import reviews from backend.simple.simple_routes import simple_routes +from backend.companies.companies_routes import companies from backend.feedback.feedback_routes import feedback import os from dotenv import load_dotenv @@ -41,9 +41,9 @@ def create_app(): # and give a url prefix to each app.logger.info('current_app(): registering blueprints with Flask app object.') app.register_blueprint(simple_routes) - app.register_blueprint(customers, url_prefix='/c') - app.register_blueprint(reviews, url_prefix='/r') + app.register_blueprint(companies, url_prefix='/c') app.register_blueprint(feedback, url_prefix='/f') + app.register_blueprint(reviews, url_prefix='/r') # Don't forget to return the app object return app diff --git a/app/src/pages/3003_Company_Profiles.py b/app/src/pages/3003_Company_Profiles.py index c74d80b638..1932df75c2 100644 --- a/app/src/pages/3003_Company_Profiles.py +++ b/app/src/pages/3003_Company_Profiles.py @@ -1,9 +1,10 @@ import logging logger = logging.getLogger(__name__) +import datetime as dt import pandas as pd +import requests import streamlit as st from streamlit_extras.app_logo import add_logo -import world_bank_data as wb import matplotlib.pyplot as plt import numpy as np import plotly.express as px @@ -18,24 +19,93 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) +# get the feedbacks +try: + companies = requests.get("http://api:4000/c/companies").json() +except: + st.write("Could not to conncet to database to get companies and roles") + +# Save DataFrame in session state +if "companies_df" not in st.session_state: + st.session_state.companies_df = pd.DataFrame(companies) - st.pyplot(test_plot) +# Title +st.title("Company and Role Manager") +# Filter settings +st.subheader("Filter and Highlight Options") +filter_by_time = st.checkbox("Filter by Last Updated Time", value=False) +highlight_missing = st.checkbox("Highlight Missing or Outdated Data", value=True) -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) \ No newline at end of file +# Time filter input +if filter_by_time: + time_threshold = st.date_input( + "Show records updated after:", dt.date(2024, 1, 1) + ) + # Convert to datetime for comparison + time_threshold = dt.datetime.combine(time_threshold, dt.datetime.min.time()) + + +company_df = st.session_state.companies_df.copy() +st.dataframe(company_df) +display_columns = ["status", "feedbackID", "userID", "timestamp", "header", "content"] +company_df = company_df[display_columns] + + +# Apply filters and highlights +if filter_by_time: + company_df = company_df[company_df["LastUpdated"] > time_threshold] + +if highlight_missing: + def highlight_conditions(row): + if row["Status"] in ["Missing Data", "Outdated"]: + return ["background-color: yellow"] * len(row) + return [""] * len(row) + + styled_df = company_df.style.apply(highlight_conditions, axis=1) + st.dataframe(styled_df) +else: + st.dataframe(company_df) + +''' +# Update or edit company profiles +st.subheader("Edit or Update Company Profiles") +company_id = st.selectbox("Select Company ID to Edit", company_df["CompanyID"]) + +# Fetch selected company data +selected_company = company_df[company_df["CompanyID"] == company_id].iloc[0] + +# Form for editing +with st.form(key="edit_form"): + company_name = st.text_input("Company Name", selected_company["CompanyName"]) + role = st.text_input("Role Description", selected_company["Role"]) + interview_details = st.text_area( + "Interview Details", selected_company["InterviewDetails"] + ) + submit_button = st.form_submit_button(label="Update Details") + + if submit_button: + st.session_state.company_data.loc[ + st.session_state.company_data["CompanyID"] == company_id, "CompanyName" + ] = company_name + st.session_state.company_data.loc[ + st.session_state.company_data["CompanyID"] == company_id, "Role" + ] = role + st.session_state.company_data.loc[ + st.session_state.company_data["CompanyID"] == company_id, "InterviewDetails" + ] = interview_details + st.session_state.company_data.loc[ + st.session_state.company_data["CompanyID"] == company_id, "LastUpdated" + ] = dt.datetime.now() + st.session_state.company_data.loc[ + st.session_state.company_data["CompanyID"] == company_id, "Status" + ] = "Complete" if role and interview_details else "Missing Data" + + st.success("Company details updated successfully!") + +# Display updated data +st.subheader("Updated Company Data") +updated_company_df = st.session_state.company_data.copy() +st.dataframe(updated_company_df) +''' diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index 8d880e5f8c..055022d91f 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -24,7 +24,9 @@ CREATE TABLE IF NOT EXISTS User ( CREATE TABLE IF NOT EXISTS Companies ( companyID INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), - description TEXT + description TEXT, + createdAt DATETIME, + updatedAT DATETIME ); diff --git a/database-files/11_CoopPlatform_Data.sql b/database-files/11_CoopPlatform_Data.sql index 77f52e6235..9d9513537b 100644 --- a/database-files/11_CoopPlatform_Data.sql +++ b/database-files/11_CoopPlatform_Data.sql @@ -38,37 +38,37 @@ INSERT INTO User (firstName, lastName, email, major, skills, interests, isAdmin, ('Grace', 'Hopper', 'grace.hopper@example.com', 'Computer Science', 'Programming, Algorithms', 'Innovation, Women in Tech', TRUE, TRUE), ('Harvey', 'Specter', 'harvey.specter@example.com', 'Law', 'Litigation, Negotiation', 'Corporate Law, Strategy', FALSE, FALSE); -INSERT INTO Companies (name, description) VALUES -('TechNova Inc.', 'A leading company in AI and machine learning solutions.'), -('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.'), -('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.'), -('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.'), -('BrightFuture Education', 'Providing online and in-person educational programs worldwide.'), -('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.'), -('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.'), -('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.'), -('GlobalTech Solutions', 'Delivering IT consulting and software development services.'), -('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.'), -('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.'), -('FinPro Banking', 'A financial services firm offering innovative banking solutions.'), -('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.'), -('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.'), -('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.'), -('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.'), -('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.'), -('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.'), -('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.'), -('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.'), -('Visionary Designs', 'Offering innovative and stylish interior design services.'), -('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.'), -('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.'), -('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.'), -('DataPulse Analytics', 'Helping businesses harness big data for decision-making.'), -('GreenTech Farms', 'Implementing innovative vertical farming solutions.'), -('CloudNet Systems', 'Offering cloud computing and data storage services.'), -('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.'), -('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.'), -('QuantumLeap Solutions', 'Researching quantum computing and its applications.'); +INSERT INTO Companies (name, description, createdAt, updatedAt) VALUES +('TechNova Inc.', 'A leading company in AI and machine learning solutions.', '2020-05-14 12:34:56', '2022-11-01 15:45:30'), +('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.', '2021-02-20 09:22:10', '2023-05-14 10:40:20'), +('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.', '2020-09-10 14:18:20', '2023-01-27 19:34:50'), +('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.', '2020-06-01 11:45:10', '2021-12-19 16:22:10'), +('BrightFuture Education', 'Providing online and in-person educational programs worldwide.', '2021-07-15 08:30:00', '2024-04-12 18:11:45'), +('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.', '2020-11-05 10:20:30', '2022-08-21 09:50:40'), +('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.', '2022-03-18 15:12:00', '2023-10-25 20:05:50'), +('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.', '2021-09-12 13:25:30', '2024-01-10 14:40:30'), +('GlobalTech Solutions', 'Delivering IT consulting and software development services.', '2021-05-25 10:50:50', '2023-07-15 17:05:20'), +('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.', '2020-12-19 14:15:45', '2022-06-30 18:25:40'), +('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.', '2020-04-10 11:10:10', '2024-03-05 10:55:00'), +('FinPro Banking', 'A financial services firm offering innovative banking solutions.', '2021-08-23 16:45:25', '2022-11-18 12:35:50'), +('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.', '2020-01-05 09:30:15', '2023-09-29 15:45:25'), +('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.', '2022-02-11 18:00:00', '2023-06-12 11:22:33'), +('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.', '2021-03-17 14:50:35', '2024-02-01 12:00:45'), +('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.', '2020-08-21 10:05:45', '2023-03-30 14:45:50'), +('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.', '2020-10-13 09:15:00', '2022-10-05 16:50:40'), +('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.', '2021-06-30 14:45:20', '2023-12-02 20:10:10'), +('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.', '2020-03-25 13:40:10', '2022-09-21 15:45:45'), +('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.', '2020-07-14 11:30:00', '2024-01-22 10:20:50'), +('Visionary Designs', 'Offering innovative and stylish interior design services.', '2021-01-10 12:15:25', '2023-05-01 09:40:30'), +('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.', '2021-04-07 14:22:30', '2023-10-15 13:45:50'), +('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.', '2020-02-19 08:45:15', '2023-07-11 17:30:20'), +('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.', '2020-11-11 12:50:45', '2024-05-20 19:50:40'), +('DataPulse Analytics', 'Helping businesses harness big data for decision-making.', '2022-01-18 10:25:00', '2023-08-30 14:55:30'), +('GreenTech Farms', 'Implementing innovative vertical farming solutions.', '2021-11-21 15:35:20', '2024-04-14 09:45:00'), +('CloudNet Systems', 'Offering cloud computing and data storage services.', '2021-10-09 17:15:45', '2023-09-03 11:05:10'), +('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.', '2020-06-08 09:45:10', '2022-05-25 18:55:40'), +('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.', '2021-07-05 13:50:50', '2024-03-19 15:20:30'), +('QuantumLeap Solutions', 'Researching quantum computing and its applications.', '2020-09-15 14:10:45', '2023-06-25 12:45:50'); From 479a53bfafaafef12a0d2116739a2b110b9b9c03 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:18:01 -0500 Subject: [PATCH 31/75] update company for admin --- app/src/pages/3003_Company_Profiles.py | 32 +++++++++++++++++-------- database-files/11_CoopPlatform_Data.sql | 3 ++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/app/src/pages/3003_Company_Profiles.py b/app/src/pages/3003_Company_Profiles.py index 1932df75c2..12b39fbe62 100644 --- a/app/src/pages/3003_Company_Profiles.py +++ b/app/src/pages/3003_Company_Profiles.py @@ -36,7 +36,9 @@ # Filter settings st.subheader("Filter and Highlight Options") filter_by_time = st.checkbox("Filter by Last Updated Time", value=False) -highlight_missing = st.checkbox("Highlight Missing or Outdated Data", value=True) +hide_location = st.checkbox("Hide Location", value=False) +highlight_missing = st.checkbox("Highlight Missing Data", value=True) + # Time filter input if filter_by_time: @@ -45,25 +47,35 @@ ) # Convert to datetime for comparison time_threshold = dt.datetime.combine(time_threshold, dt.datetime.min.time()) + company_df = st.session_state.companies_df.copy() -st.dataframe(company_df) -display_columns = ["status", "feedbackID", "userID", "timestamp", "header", "content"] +company_df = company_df.rename(columns={'I.name': 'Industry', 'R.description':'Role Description', 'address':'Address', 'city':'City', 'country': 'Country', 'description':'Company Description', 'name': 'Company Name', 'roleName': 'Role Name', 'skillsRequired':'Skills Required', 'state_province':'State Province','updatedAT': 'Last Updated'}) +display_columns = ["Company Name", "Last Updated", "Industry", "Company Description", "Role Name", "Skills Required", "Role Description", "Address", "City", "State Province", "Country"] company_df = company_df[display_columns] +company_df['Last Updated'] = pd.to_datetime(company_df['Last Updated']) # Apply filters and highlights if filter_by_time: - company_df = company_df[company_df["LastUpdated"] > time_threshold] + company_df = company_df[company_df["Last Updated"] > time_threshold] -if highlight_missing: - def highlight_conditions(row): - if row["Status"] in ["Missing Data", "Outdated"]: - return ["background-color: yellow"] * len(row) - return [""] * len(row) +if hide_location: + company_df = company_df.drop(columns = ["Address", "City", "State Province", "Country"]) +#st.dataframe(company_df) - styled_df = company_df.style.apply(highlight_conditions, axis=1) +if highlight_missing: + def highlight_null_rows(df): + def highlight_row(row): + if row.isnull().any(): + return ['background-color: yellow'] * len(row) + else: + return [''] * len(row) + + return df.style.apply(highlight_row, axis=1) + + styled_df = highlight_null_rows(company_df) st.dataframe(styled_df) else: st.dataframe(company_df) diff --git a/database-files/11_CoopPlatform_Data.sql b/database-files/11_CoopPlatform_Data.sql index 9d9513537b..ff80e3f0a8 100644 --- a/database-files/11_CoopPlatform_Data.sql +++ b/database-files/11_CoopPlatform_Data.sql @@ -42,7 +42,8 @@ INSERT INTO Companies (name, description, createdAt, updatedAt) VALUES ('TechNova Inc.', 'A leading company in AI and machine learning solutions.', '2020-05-14 12:34:56', '2022-11-01 15:45:30'), ('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.', '2021-02-20 09:22:10', '2023-05-14 10:40:20'), ('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.', '2020-09-10 14:18:20', '2023-01-27 19:34:50'), -('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.', '2020-06-01 11:45:10', '2021-12-19 16:22:10'), +('EcoEnergy Co.', NULL, '2020-06-01 11:45:10', '2021-12-19 16:22:10'), +#('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.', '2020-06-01 11:45:10', '2021-12-19 16:22:10'), ('BrightFuture Education', 'Providing online and in-person educational programs worldwide.', '2021-07-15 08:30:00', '2024-04-12 18:11:45'), ('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.', '2020-11-05 10:20:30', '2022-08-21 09:50:40'), ('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.', '2022-03-18 15:12:00', '2023-10-25 20:05:50'), From 74df4237c6fc48a4bed7e286c4e03560713a3fb4 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 22:02:27 -0500 Subject: [PATCH 32/75] searcher routes updated --- api/backend/coop_searcher/searcher_routes.py | 39 ++ api/backend/rest_entry.py | 14 +- api/backend/reviews/reviews_routes.py | 3 - .../pages/1001_Company_Position_Reviews.py | 31 +- database-files/10_coopPlatformDB.sql | 12 +- database-files/11_CoopPlatform.sql | 393 ------------------ database-files/11_CoopPlatform_Data.sql | 393 ------------------ database-files/12_CoopPlatform_Data.sql | 31 ++ 8 files changed, 89 insertions(+), 827 deletions(-) create mode 100644 api/backend/coop_searcher/searcher_routes.py delete mode 100644 database-files/11_CoopPlatform.sql delete mode 100644 database-files/11_CoopPlatform_Data.sql diff --git a/api/backend/coop_searcher/searcher_routes.py b/api/backend/coop_searcher/searcher_routes.py new file mode 100644 index 0000000000..ff77d81560 --- /dev/null +++ b/api/backend/coop_searcher/searcher_routes.py @@ -0,0 +1,39 @@ +######################################################## +# Sample customers blueprint of endpoints +# Remove this file if you are not using it in your project +######################################################## +from flask import Blueprint +from flask import request +from flask import jsonify +from flask import make_response +from flask import current_app +from backend.db_connection import db +from backend.ml_models.model01 import predict + +#------------------------------------------------------------ +# Create a new Blueprint object, which is a collection of +# routes. +searcher = Blueprint('coop_searcher', __name__) + +#------------------------------------------------------------ +# Get all customers from the system +@searcher.route('/companiesWithReviews', methods=['GET']) +def get_companies_with_reviews(): + + query = ''' + SELECT DISTINCT c.name AS CompanyName + FROM Companies c + JOIN Role r ON c.companyID = r.companyID + JOIN Reviews rv ON r.roleID = rv.roleID; + ''' + + # get the database connection, execute the query, and + # fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response \ No newline at end of file diff --git a/api/backend/rest_entry.py b/api/backend/rest_entry.py index d44fc1ff25..f5e1e5e7d8 100644 --- a/api/backend/rest_entry.py +++ b/api/backend/rest_entry.py @@ -1,16 +1,11 @@ from flask import Flask from backend.db_connection import db -<<<<<<< HEAD -from backend.customers.customer_routes import customers -from backend.reviews.reviews_routes import reviews -from backend.simple.simple_routes import simple_routes -======= from backend.reviews.reviews_routes import reviews from backend.simple.simple_routes import simple_routes from backend.companies.companies_routes import companies ->>>>>>> 1a7805cdae2c5c2a740b690b50489d4caf4191d4 from backend.feedback.feedback_routes import feedback +from backend.coop_searcher.searcher_routes import searcher import os from dotenv import load_dotenv @@ -47,15 +42,10 @@ def create_app(): # and give a url prefix to each app.logger.info('current_app(): registering blueprints with Flask app object.') app.register_blueprint(simple_routes) -<<<<<<< HEAD - app.register_blueprint(customers, url_prefix='/c') - app.register_blueprint(reviews, url_prefix='/r') - app.register_blueprint(feedback, url_prefix='/f') -======= app.register_blueprint(companies, url_prefix='/c') app.register_blueprint(feedback, url_prefix='/f') app.register_blueprint(reviews, url_prefix='/r') ->>>>>>> 1a7805cdae2c5c2a740b690b50489d4caf4191d4 + app.register_blueprint(searcher, url_prefix='/s') # Don't forget to return the app object return app diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index 2c4b7252f1..19539f9937 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -16,8 +16,6 @@ reviews = Blueprint('reviews', __name__) -<<<<<<< HEAD -======= @reviews.route('/addReview', methods=['POST']) def add_review(): review_data = request.json @@ -47,7 +45,6 @@ def add_review(): print(traceback.format_exc()) return jsonify({"error": error_message}), 500 ->>>>>>> 1a7805cdae2c5c2a740b690b50489d4caf4191d4 # ------------------------------------------------------------ # get product information about a specific product # notice that the route takes and then you see id diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index c02f6ec1a8..abf1a180bd 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -1,13 +1,8 @@ import logging logger = logging.getLogger(__name__) -import pandas as pd import streamlit as st -from streamlit_extras.app_logo import add_logo -import world_bank_data as wb -import matplotlib.pyplot as plt -import numpy as np -import plotly.express as px from modules.nav import SideBarLinks +import requests # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() @@ -18,24 +13,10 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) +results = requests.get(f'http://api:4000/s/companiesWithReviews').json() -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) +# Extract company names into a list +company_names = [item["CompanyName"] for item in results] - st.pyplot(test_plot) - - -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) +# Display a dropdown menu with company names +selected_company = st.selectbox("Select a Company:", company_names) \ No newline at end of file diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index 055022d91f..9f6cb621d9 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -136,7 +136,17 @@ CREATE TABLE IF NOT EXISTS Feedback ( FOREIGN KEY (userID) REFERENCES User(userID) ); - +-- Create InterviewReports table +CREATE TABLE IF NOT EXISTS InterviewReports ( + reportID INT AUTO_INCREMENT PRIMARY KEY, + roleID INT, + userID INT, + interviewDate DATE, + difficultyLevel VARCHAR(50), + tips TEXT, + FOREIGN KEY (roleID) REFERENCES Role(roleID), + FOREIGN KEY (userID) REFERENCES User(userID) +); diff --git a/database-files/11_CoopPlatform.sql b/database-files/11_CoopPlatform.sql deleted file mode 100644 index de87906064..0000000000 --- a/database-files/11_CoopPlatform.sql +++ /dev/null @@ -1,393 +0,0 @@ --- Use the newly created database -USE CoopPlatform; - - -INSERT INTO User (firstName, lastName, email, major, skills, interests, isAdmin, isAnalyst) VALUES -('Alice', 'Smith', 'alice.smith@example.com', 'Computer Science', 'Java, Python', 'AI, Robotics', FALSE, TRUE), -('Bob', 'Johnson', 'bob.johnson@example.com', 'Mathematics', 'R, MATLAB', 'Statistics, Data Science', FALSE, TRUE), -('Charlie', 'Brown', 'charlie.brown@example.com', 'Physics', 'C++, Fortran', 'Quantum Mechanics, Astrophysics', FALSE, FALSE), -('Diana', 'Prince', 'diana.prince@example.com', 'Electrical Engineering', 'C, Embedded Systems', 'Renewable Energy, IoT', FALSE, FALSE), -('Ethan', 'Hunt', 'ethan.hunt@example.com', 'Cybersecurity', 'Networking, Ethical Hacking', 'Digital Security, Cryptography', FALSE, TRUE), -('Fiona', 'Gallagher', 'fiona.gallagher@example.com', 'Psychology', 'SPSS, Data Analysis', 'Behavioral Studies, Neuropsychology', FALSE, FALSE), -('George', 'Michaels', 'george.michaels@example.com', 'Business', 'Excel, SQL', 'Entrepreneurship, Management', FALSE, FALSE), -('Hannah', 'Montana', 'hannah.montana@example.com', 'Music', 'Composition, Audio Editing', 'Songwriting, Producing', FALSE, FALSE), -('Ian', 'Malcolm', 'ian.malcolm@example.com', 'Biology', 'Genetics, Bioinformatics', 'Evolution, Conservation', FALSE, TRUE), -('Julia', 'Roberts', 'julia.roberts@example.com', 'Drama', 'Acting, Directing', 'Theater, Film Studies', FALSE, FALSE), -('Kevin', 'Hart', 'kevin.hart@example.com', 'Performing Arts', 'Comedy, Storytelling', 'Improv, Stand-up', FALSE, FALSE), -('Laura', 'Croft', 'laura.croft@example.com', 'Archaeology', 'Field Research, Mapping', 'Ancient Civilizations, Exploration', FALSE, TRUE), -('Michael', 'Scott', 'michael.scott@example.com', 'Business Administration', 'Leadership, Communication', 'Sales, Marketing', TRUE, FALSE), -('Nancy', 'Drew', 'nancy.drew@example.com', 'Criminology', 'Investigation, Profiling', 'Mysteries, Forensics', FALSE, FALSE), -('Oliver', 'Queen', 'oliver.queen@example.com', 'Political Science', 'Policy Analysis, Strategy', 'Social Justice, Governance', FALSE, FALSE), -('Penelope', 'Garcia', 'penelope.garcia@example.com', 'Information Systems', 'Database Management, Programming', 'Technology, Cybersecurity', FALSE, TRUE), -('Quincy', 'Jones', 'quincy.jones@example.com', 'Music', 'Arranging, Producing', 'Jazz, Classical', FALSE, FALSE), -('Rachel', 'Green', 'rachel.green@example.com', 'Fashion Design', 'Sketching, Sewing', 'Trends, Styling', FALSE, FALSE), -('Steve', 'Jobs', 'steve.jobs@example.com', 'Product Design', 'Innovation, Prototyping', 'Technology, Design Thinking', FALSE, TRUE), -('Tracy', 'Morgan', 'tracy.morgan@example.com', 'Comedy Writing', 'Humor, Screenwriting', 'Sitcoms, Stand-up', FALSE, FALSE), -('Uma', 'Thurman', 'uma.thurman@example.com', 'Film Studies', 'Directing, Editing', 'Cinema, Storytelling', FALSE, FALSE), -('Victor', 'Frankenstein', 'victor.frankenstein@example.com', 'Biotechnology', 'CRISPR, Synthetic Biology', 'Genetic Engineering, Bioethics', FALSE, TRUE), -('Will', 'Smith', 'will.smith@example.com', 'Acting', 'Acting, Producing', 'Film, Music', FALSE, FALSE), -('Xander', 'Harris', 'xander.harris@example.com', 'History', 'Archival Research, Writing', 'Medieval History, Literature', FALSE, FALSE), -('Yara', 'Greyjoy', 'yara.greyjoy@example.com', 'Marine Biology', 'Oceanography, Diving', 'Marine Conservation, Ecology', FALSE, TRUE), -('Zara', 'Larsson', 'zara.larsson@example.com', 'Music Production', 'Singing, Mixing', 'Pop Music, Performance', FALSE, FALSE), -('Adam', 'West', 'adam.west@example.com', 'Theater', 'Acting, Public Speaking', 'Drama, Performance', FALSE, FALSE), -('Bella', 'Swan', 'bella.swan@example.com', 'Literature', 'Creative Writing, Editing', 'Romance, Fiction', FALSE, FALSE), -('Chris', 'Evans', 'chris.evans@example.com', 'Film Production', 'Editing, Cinematography', 'Action, Direction', FALSE, TRUE), -('Derek', 'Shepherd', 'derek.shepherd@example.com', 'Medicine', 'Surgery, Research', 'Neurosurgery, Health Care', FALSE, FALSE), -('Evelyn', 'Salt', 'evelyn.salt@example.com', 'International Relations', 'Negotiation, Strategy', 'Conflict Resolution, Diplomacy', FALSE, FALSE), -('Finn', 'Hudson', 'finn.hudson@example.com', 'Music Education', 'Choir, Performance', 'Teaching, Vocal Training', FALSE, FALSE), -('Grace', 'Hopper', 'grace.hopper@example.com', 'Computer Science', 'Programming, Algorithms', 'Innovation, Women in Tech', TRUE, TRUE), -('Harvey', 'Specter', 'harvey.specter@example.com', 'Law', 'Litigation, Negotiation', 'Corporate Law, Strategy', FALSE, FALSE); - -INSERT INTO Companies (name, description, createdAt, updatedAt) VALUES -('TechNova Inc.', 'A leading company in AI and machine learning solutions.', '2020-05-14 12:34:56', '2022-11-01 15:45:30'), -('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.', '2021-02-20 09:22:10', '2023-05-14 10:40:20'), -('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.', '2020-09-10 14:18:20', '2023-01-27 19:34:50'), -('EcoEnergy Co.', NULL, '2020-06-01 11:45:10', '2021-12-19 16:22:10'), -#('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.', '2020-06-01 11:45:10', '2021-12-19 16:22:10'), -('BrightFuture Education', 'Providing online and in-person educational programs worldwide.', '2021-07-15 08:30:00', '2024-04-12 18:11:45'), -('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.', '2020-11-05 10:20:30', '2022-08-21 09:50:40'), -('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.', '2022-03-18 15:12:00', '2023-10-25 20:05:50'), -('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.', '2021-09-12 13:25:30', '2024-01-10 14:40:30'), -('GlobalTech Solutions', 'Delivering IT consulting and software development services.', '2021-05-25 10:50:50', '2023-07-15 17:05:20'), -('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.', '2020-12-19 14:15:45', '2022-06-30 18:25:40'), -('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.', '2020-04-10 11:10:10', '2024-03-05 10:55:00'), -('FinPro Banking', 'A financial services firm offering innovative banking solutions.', '2021-08-23 16:45:25', '2022-11-18 12:35:50'), -('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.', '2020-01-05 09:30:15', '2023-09-29 15:45:25'), -('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.', '2022-02-11 18:00:00', '2023-06-12 11:22:33'), -('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.', '2021-03-17 14:50:35', '2024-02-01 12:00:45'), -('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.', '2020-08-21 10:05:45', '2023-03-30 14:45:50'), -('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.', '2020-10-13 09:15:00', '2022-10-05 16:50:40'), -('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.', '2021-06-30 14:45:20', '2023-12-02 20:10:10'), -('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.', '2020-03-25 13:40:10', '2022-09-21 15:45:45'), -('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.', '2020-07-14 11:30:00', '2024-01-22 10:20:50'), -('Visionary Designs', 'Offering innovative and stylish interior design services.', '2021-01-10 12:15:25', '2023-05-01 09:40:30'), -('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.', '2021-04-07 14:22:30', '2023-10-15 13:45:50'), -('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.', '2020-02-19 08:45:15', '2023-07-11 17:30:20'), -('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.', '2020-11-11 12:50:45', '2024-05-20 19:50:40'), -('DataPulse Analytics', 'Helping businesses harness big data for decision-making.', '2022-01-18 10:25:00', '2023-08-30 14:55:30'), -('GreenTech Farms', 'Implementing innovative vertical farming solutions.', '2021-11-21 15:35:20', '2024-04-14 09:45:00'), -('CloudNet Systems', 'Offering cloud computing and data storage services.', '2021-10-09 17:15:45', '2023-09-03 11:05:10'), -('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.', '2020-06-08 09:45:10', '2022-05-25 18:55:40'), -('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.', '2021-07-05 13:50:50', '2024-03-19 15:20:30'), -('QuantumLeap Solutions', 'Researching quantum computing and its applications.', '2020-09-15 14:10:45', '2023-06-25 12:45:50'); - - - - -INSERT INTO Industries (name) VALUES -('Information Technology'), -('Healthcare'), -('Education'), -('Finance'), -('Automotive'), -('Biotechnology'), -('Aerospace'), -('Renewable Energy'), -('Construction'), -('Entertainment'), -('Robotics'), -('Logistics'), -('Cybersecurity'), -('Sports and Recreation'), -('Real Estate'), -('Food and Beverage'), -('Interior Design'), -('Pet Care'), -('Travel and Tourism'), -('Manufacturing'), -('Data Analytics'), -('Agriculture'), -('Cloud Computing'), -('Arts and Crafts'), -('E-commerce'), -('Quantum Computing'), -('Fashion and Apparel'), -('Gaming'), -('Pharmaceuticals'), -('Marine and Aquatic Technologies'); - - -INSERT INTO CompanyIndustry (companyID, industryID) VALUES -(1, 1), -- TechNova Inc. -> Information Technology -(1, 13), -- TechNova Inc. -> Cybersecurity -(2, 22), -- GreenFields Ltd. -> Agriculture -(2, 8), -- GreenFields Ltd. -> Renewable Energy -(3, 7), -- SkyHigh Aerospace -> Aerospace -(4, 8), -- EcoEnergy Co. -> Renewable Energy -(4, 21), -- EcoEnergy Co. -> Manufacturing -(5, 3), -- BrightFuture Education -> Education -(6, 2), -- HealthCore Pharmaceuticals -> Healthcare -(6, 30), -- HealthCore Pharmaceuticals -> Pharmaceuticals -(7, 9), -- UrbanBuilders LLC -> Construction -(8, 30), -- AquaLife Systems -> Marine and Aquatic Technologies -(9, 1), -- GlobalTech Solutions -> Information Technology -(10, 10), -- Stellar Entertainment -> Entertainment -(11, 12), -- NextGen Robotics -> Robotics -(11, 21), -- NextGen Robotics -> Manufacturing -(12, 4), -- FinPro Banking -> Finance -(13, 5), -- AutoFuture Ltd. -> Automotive -(13, 21), -- AutoFuture Ltd. -> Manufacturing -(14, 6), -- BioGenomics Inc. -> Biotechnology -(14, 30), -- BioGenomics Inc. -> Pharmaceuticals -(15, 12), -- BlueOcean Logistics -> Logistics -(16, 13), -- CyberShield Security -> Cybersecurity -(17, 14), -- Peak Performance Sports -> Sports and Recreation -(18, 9), -- EcoHomes Construction -> Construction -(18, 8), -- EcoHomes Construction -> Renewable Energy -(19, 1), -- VirtuMed Technologies -> Information Technology -(19, 3), -- VirtuMed Technologies -> Education -(20, 17), -- Gourmet World Foods -> Food and Beverage -(21, 10), -- Visionary Designs -> Interior Design -(22, 18), -- PetCare Innovations -> Pet Care -(23, 19), -- TravelSphere Ltd. -> Travel and Tourism -(24, 21), -- FusionTech Manufacturing -> Manufacturing -(25, 20), -- DataPulse Analytics -> Data Analytics -(26, 22), -- GreenTech Farms -> Agriculture -(27, 23), -- CloudNet Systems -> Cloud Computing -(28, 24), -- ArtisanCrafts Co. -> Arts and Crafts -(29, 25), -- BrightPath Logistics -> E-commerce -(30, 26); -- QuantumLeap Solutions -> Quantum Computing - -INSERT INTO Location (companyID, address, city, state_province, country) VALUES -(1, '123 Innovation Blvd', 'San Francisco', 'California', 'USA'), -(2, '456 Greenway Rd', 'Seattle', 'Washington', 'USA'), -(3, '789 SkyHigh Dr', 'Huntsville', 'Alabama', 'USA'), -(4, '321 Solar St', 'Austin', 'Texas', 'USA'), -(5, '654 Bright Ln', 'Boston', 'Massachusetts', 'USA'), -(6, '987 Pharma Ave', 'Cambridge', 'Massachusetts', 'USA'), -(7, '111 Builder Way', 'New York', 'New York', 'USA'), -(8, '222 Water Works', 'Miami', 'Florida', 'USA'), -(9, '333 Tech Plaza', 'San Jose', 'California', 'USA'), -(10, '444 Entertainment Row', 'Los Angeles', 'California', 'USA'), -(11, '555 Robotics St', 'Pittsburgh', 'Pennsylvania', 'USA'), -(12, '666 Finance Blvd', 'Chicago', 'Illinois', 'USA'), -(13, '777 Auto Ln', 'Detroit', 'Michigan', 'USA'), -(14, '888 BioTech Rd', 'San Diego', 'California', 'USA'), -(15, '999 Ocean Dr', 'Savannah', 'Georgia', 'USA'), -(16, '121 Cyber Ave', 'Austin', 'Texas', 'USA'), -(17, '131 Sports Way', 'Portland', 'Oregon', 'USA'), -(18, '141 Eco Homes Blvd', 'Denver', 'Colorado', 'USA'), -(19, '151 MedTech Dr', 'Houston', 'Texas', 'USA'), -(20, '161 Gourmet St', 'Paris', 'Île-de-France', 'France'), -(21, '171 Design Ln', 'Milan', 'Lombardy', 'Italy'), -(22, '181 PetCare Way', 'Sydney', 'New South Wales', 'Australia'), -(23, '191 Travel Blvd', 'London', 'England', 'United Kingdom'), -(24, '201 FusionTech Rd', 'Munich', 'Bavaria', 'Germany'), -(25, '211 DataPulse Ave', 'Toronto', 'Ontario', 'Canada'), -(26, '221 Green Farms Rd', 'Amsterdam', 'North Holland', 'Netherlands'), -(27, '231 CloudNet Dr', 'Dublin', 'Leinster', 'Ireland'), -(28, '241 Artisan Row', 'Kyoto', 'Kyoto Prefecture', 'Japan'), -(29, '251 BrightPath Blvd', 'Shanghai', 'Shanghai', 'China'), -(30, '261 Quantum Leap Way', 'Zurich', 'Zurich', 'Switzerland'), -(1, '271 Silicon Way', 'Palo Alto', 'California', 'USA'), -(12, '282 Green Circle', 'Vancouver', 'British Columbia', 'Canada'), -(23, '293 Spaceport Dr', 'Cape Canaveral', 'Florida', 'USA'), -(24, '304 Renewable St', 'Berlin', 'Berlin', 'Germany'), -(5, '315 BrightStar Rd', 'Oslo', 'Oslo', 'Norway'), -(6, '326 Pharma Labs', 'Hyderabad', 'Telangana', 'India'), -(27, '337 Builder Ln', 'Tokyo', 'Tokyo Prefecture', 'Japan'), -(18, '348 Aqua Center', 'Cape Town', 'Western Cape', 'South Africa'), -(19, '359 TechHub Blvd', 'Bangalore', 'Karnataka', 'India'), -(10, '370 Creative Row', 'Stockholm', 'Stockholm County', 'Sweden'), -(21, '381 Robotics Ave', 'Seoul', 'Seoul', 'South Korea'), -(30, '392 Financial Way', 'Zurich', 'Zurich', 'Switzerland'), -(23, '403 Auto Plaza', 'Stuttgart', 'Baden-Württemberg', 'Germany'), -(14, '414 Biotech Blvd', 'Tel Aviv', 'Tel Aviv District', 'Israel'), -(5, '425 Logistics Lane', 'Dubai', 'Dubai', 'United Arab Emirates'); - -INSERT INTO Role (companyID, locationID, roleName, description, skillsRequired) VALUES -(1, 1, 'Machine Learning Engineer', 'Design and implement machine learning models for real-world applications.', 'Python, TensorFlow, Data Analysis'), -(2, 2, 'Sustainability Analyst', 'Analyze and optimize sustainable farming practices.', 'Data Analysis, Agricultural Science'), -(3, 3, 'Aerospace Engineer', 'Develop advanced spacecraft and satellite systems.', 'C++, Aerodynamics, CAD'), -(4, 4, 'Renewable Energy Consultant', 'Consult on renewable energy projects and strategies.', 'Project Management, Solar Technology'), -(5, 5, 'Educational Content Developer', 'Create engaging educational materials for online learning.', 'Curriculum Design, Content Writing'), -(6, 6, 'Clinical Research Scientist', 'Conduct research on pharmaceutical treatments and solutions.', 'Pharmacology, Research Methods'), -(7, 7, 'Architectural Designer', 'Design urban structures and smart city layouts.', 'AutoCAD, Urban Planning'), -(8, 8, 'Water Systems Engineer', 'Develop innovative water purification and desalination systems.', 'Hydraulics, System Design'), -(9, 9, 'Software Developer', 'Build scalable software solutions for clients.', 'Java, SQL, Cloud Platforms'), -(10, 10, 'Video Producer', 'Produce and manage video content for global distribution.', 'Adobe Premiere, Cinematography'), -(11, 11, 'Robotics Engineer', 'Develop robotics solutions for industrial applications.', 'Python, Robotics Frameworks'), -(12, 12, 'Financial Analyst', 'Analyze financial data to provide strategic advice.', 'Excel, Financial Modeling'), -(13, 13, 'Automotive Engineer', 'Design and test autonomous vehicle systems.', 'Matlab, Simulink, AI'), -(14, 14, 'Biotechnology Researcher', 'Conduct research in genetic engineering and biotechnology.', 'CRISPR, Lab Techniques'), -(15, 15, 'Logistics Manager', 'Oversee and optimize supply chain operations.', 'Supply Chain Management, SAP'), -(16, 16, 'Cybersecurity Specialist', 'Protect systems from cyber threats and vulnerabilities.', 'Penetration Testing, Network Security'), -(17, 17, 'Sports Equipment Designer', 'Design high-performance sports equipment.', 'Material Science, CAD'), -(18, 18, 'Eco-Friendly Construction Manager', 'Lead eco-friendly building projects.', 'Project Management, Green Building Standards'), -(19, 19, 'Virtual Reality Developer', 'Develop VR applications for medical training.', 'Unity, C#, 3D Modeling'), -(20, 20, 'Food Product Manager', 'Manage and oversee the development of gourmet food products.', 'Food Science, Marketing'), -(21, 21, 'Interior Designer', 'Create innovative and stylish interior designs.', 'Sketching, 3D Rendering'), -(22, 22, 'Veterinary Product Specialist', 'Develop and promote veterinary products.', 'Animal Science, Product Development'), -(23, 23, 'Tour Guide Manager', 'Coordinate and manage unique travel experiences.', 'Hospitality Management, Customer Service'), -(24, 24, 'Manufacturing Process Engineer', 'Optimize manufacturing processes and workflows.', 'Process Design, Lean Manufacturing'), -(25, 25, 'Data Scientist', 'Analyze big data for actionable insights.', 'Python, Machine Learning, Data Visualization'), -(26, 26, 'Agricultural Engineer', 'Implement innovative agricultural technologies.', 'Mechanical Engineering, Agricultural Systems'), -(27, 27, 'Cloud Infrastructure Engineer', 'Manage and deploy cloud-based solutions.', 'AWS, Kubernetes, Networking'), -(28, 28, 'Artisan Product Designer', 'Design and promote handcrafted artisan products.', 'Creativity, Marketing'), -(29, 29, 'E-commerce Operations Manager', 'Manage e-commerce logistics and operations.', 'Inventory Management, Analytics'), -(30, 30, 'Quantum Computing Researcher', 'Research and develop quantum computing applications.', 'Quantum Mechanics, Algorithms'); - -INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES -(1, 1, '2024-01-01 10:00:00', 'Experience', 'Great Experience as an ML Engineer', 'I had a fantastic experience working as a Machine Learning Engineer at TechNova Inc. Learned a lot about AI.', 150, 35, FALSE), -(2, 2, '2024-01-05 15:30:00', 'Feedback', 'Improved Sustainability Practices', 'The company is making significant strides in sustainability, but communication needs improvement.', 100, 20, FALSE), -(3, 3, '2024-01-10 09:45:00', 'Review', 'Exciting Role in Aerospace', 'Working on cutting-edge technology was inspiring. Would recommend it to any aspiring engineer.', 200, 50, FALSE), -(4, 4, '2024-01-15 14:20:00', 'Insight', 'Great Opportunity in Renewable Energy', 'A rewarding experience with excellent leadership and vision.', 120, 25, FALSE), -(5, 5, '2024-01-20 11:10:00', 'Experience', 'Rewarding Work Environment', 'Collaborative culture and strong focus on education made my role enjoyable.', 90, 15, FALSE), -(6, 6, '2024-01-25 17:00:00', 'Feedback', 'Cutting-Edge Research', 'Involved in exciting research but workload was quite heavy.', 140, 30, FALSE), -(7, 7, '2024-02-01 08:00:00', 'Review', 'Urban Development at Its Best', 'Loved working on innovative projects for smart cities.', 85, 10, FALSE), -(8, 8, '2024-02-05 10:30:00', 'Insight', 'Advancing Water Purification', 'Meaningful work but limited opportunities for growth.', 70, 12, FALSE), -(9, 9, '2024-02-10 13:15:00', 'Experience', 'Dynamic Work Environment', 'Fast-paced and challenging, great place for software enthusiasts.', 180, 40, FALSE), -(10, 10, '2024-02-15 16:45:00', 'Feedback', 'Creative and Supportive', 'Perfect workplace for creative professionals.', 75, 18, FALSE), -(11, 11, '2024-02-20 19:20:00', 'Review', 'Robotics Projects Worth Pursuing', 'Exciting projects but management needs improvement.', 95, 20, FALSE), -(12, 12, '2024-02-25 07:30:00', 'Insight', 'Great Start for Financial Analysts', 'Supportive team and ample learning opportunities.', 105, 22, FALSE), -(13, 13, '2024-03-01 11:50:00', 'Experience', 'Innovative Role in Automotive', 'Hands-on experience with cutting-edge technologies.', 130, 35, FALSE), -(14, 14, '2024-03-05 09:40:00', 'Feedback', 'Inspiring Research Environment', 'Focus on innovation, but better work-life balance needed.', 165, 28, FALSE), -(15, 15, '2024-03-10 12:25:00', 'Review', 'Streamlined Logistics Management', 'Efficient processes and a dynamic team.', 80, 14, FALSE), -(16, 16, '2024-03-15 14:00:00', 'Insight', 'Top-notch Cybersecurity Expertise', 'Fantastic workplace for security professionals.', 200, 50, FALSE), -(17, 17, '2024-03-20 15:30:00', 'Experience', 'Challenging Sports Equipment Design', 'Opportunity to innovate, but tight deadlines.', 60, 10, FALSE), -(18, 18, '2024-03-25 16:45:00', 'Feedback', 'Sustainable and Collaborative', 'Loved the eco-friendly approach and teamwork.', 95, 25, FALSE), -(19, 19, '2024-03-30 10:10:00', 'Review', 'Immersive VR Development', 'Great exposure to VR development, but lacked mentorship.', 120, 18, FALSE), -(20, 20, '2024-04-01 13:00:00', 'Insight', 'Delicious Career Growth', 'Enjoyed working on gourmet food projects.', 80, 16, FALSE), -(21, 21, '2024-04-05 14:30:00', 'Experience', 'Creative Interior Design Projects', 'Amazing projects but needs better client communication.', 110, 20, FALSE), -(22, 22, '2024-04-10 09:15:00', 'Feedback', 'Innovative Pet Products', 'Great workplace with a fun and collaborative culture.', 90, 22, FALSE), -(23, 23, '2024-04-15 10:45:00', 'Review', 'Rewarding Travel Role', 'TravelSphere provides ample learning opportunities.', 115, 18, FALSE), -(24, 24, '2024-04-20 11:30:00', 'Insight', 'Streamlined Manufacturing Process', 'High-tech projects but long hours.', 130, 24, FALSE), -(25, 25, '2024-04-25 16:00:00', 'Experience', 'Data-Driven Insights', 'DataPulse offers cutting-edge analytics projects.', 170, 40, FALSE), -(26, 26, '2024-05-01 09:40:00', 'Feedback', 'Smart Agricultural Practices', 'Good place to grow for agricultural engineers.', 140, 35, FALSE), -(27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), -(28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), -(29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), -(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE); - - -INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagged) VALUES -(1, 2, NULL, 'This sounds like a fantastic experience! Thanks for sharing.', 10, FALSE), -(1, 3, 1, 'Absolutely agree! I had a similar experience.', 5, FALSE), -(2, 4, NULL, 'Do you think the communication issue is company-wide?', 8, FALSE), -(2, 1, 4, 'Yes, I think it varies by team, but it’s something to improve.', 6, FALSE), -(3, 5, NULL, 'Aerospace is such an exciting field. How was the workload?', 12, FALSE), -(4, 6, NULL, 'I’ve been considering applying here. Any tips for getting in?', 15, FALSE), -(4, 2, 6, 'Focus on renewable energy projects in your portfolio.', 7, FALSE), -(5, 7, NULL, 'I love collaborative environments. Sounds like a great role.', 4, FALSE), -(6, 8, NULL, 'Heavy workloads can be tough. Was the management supportive?', 9, FALSE), -(6, 9, 8, 'They were supportive but often stretched thin.', 3, FALSE), -(7, 10, NULL, 'Smart cities are the future. How innovative were the projects?', 13, FALSE), -(8, 11, NULL, 'What kind of growth opportunities were you hoping for?', 6, FALSE), -(8, 3, 11, 'Leadership roles or cross-functional projects.', 4, FALSE), -(9, 12, NULL, 'Tech companies often have dynamic environments. Did you feel valued?', 11, FALSE), -(10, 13, NULL, 'Supportive workplaces are so important for creatives.', 8, FALSE), -(11, 14, NULL, 'Robotics is fascinating! What kind of robots did you work on?', 14, FALSE), -(11, 15, 14, 'Mostly industrial robots for manufacturing.', 7, FALSE), -(12, 16, NULL, 'Finance is challenging. Did you have a good team?', 10, FALSE), -(13, 17, NULL, 'I’d love to work on autonomous vehicles. Any advice?', 18, FALSE), -(14, 18, NULL, 'How innovative was the genetic research you were involved in?', 20, FALSE), -(14, 19, 18, 'Very cutting-edge, especially in CRISPR technology.', 12, FALSE), -(15, 20, NULL, 'Efficient logistics management is key to success.', 9, FALSE), -(16, 21, NULL, 'What kind of tools were used for cybersecurity?', 11, FALSE), -(16, 22, 21, 'Mostly Splunk, Wireshark, and custom tools.', 5, FALSE), -(17, 23, NULL, 'Tight deadlines can be tough. How was the work-life balance?', 7, FALSE), -(18, 24, NULL, 'Eco-friendly construction is inspiring. What projects stood out?', 14, FALSE), -(19, 25, NULL, 'VR development is fascinating. What applications did you focus on?', 17, FALSE), -(19, 26, 25, 'Medical training simulations. Very impactful.', 10, FALSE), -(20, 27, NULL, 'Gourmet food development sounds interesting! How creative was it?', 8, FALSE), -(21, 28, NULL, 'Interior design is so rewarding. What was your favorite project?', 13, FALSE); - - -INSERT INTO Badges (badgeName) VALUES -('Top Contributor'), -('Expert Reviewer'), -('Helpful Commenter'), -('Insightful Reviewer'), -('Early Adopter'), -('Collaboration Champion'), -('Creative Thinker'), -('Innovation Advocate'), -('Team Player'), -('Knowledge Sharer'), -('Problem Solver'), -('Critical Thinker'), -('Community Builder'), -('Leadership Star'), -('Data Enthusiast'); - - -INSERT INTO UserBadges (userID, badgeID) VALUES -(1, 1), -- User 1: Top Contributor -(1, 2), -- User 1: Expert Reviewer -(2, 3), -- User 2: Helpful Commenter -(2, 4), -- User 2: Insightful Reviewer -(3, 5), -- User 3: Early Adopter -(4, 6), -- User 4: Collaboration Champion -(4, 7), -- User 4: Creative Thinker -(5, 8), -- User 5: Innovation Advocate -(6, 9), -- User 6: Team Player -(6, 10), -- User 6: Knowledge Sharer -(7, 11), -- User 7: Problem Solver -(8, 12), -- User 8: Critical Thinker -(9, 13), -- User 9: Community Builder -(10, 14), -- User 10: Leadership Star -(11, 15), -- User 11: Data Enthusiast -(12, 1), -- User 12: Top Contributor -(13, 4), -- User 13: Insightful Reviewer -(14, 6), -- User 14: Collaboration Champion -(15, 7), -- User 15: Creative Thinker -(16, 8), -- User 16: Innovation Advocate -(17, 3), -- User 17: Helpful Commenter -(18, 10), -- User 18: Knowledge Sharer -(19, 11), -- User 19: Problem Solver -(20, 12), -- User 20: Critical Thinker -(21, 13), -- User 21: Community Builder -(22, 14), -- User 22: Leadership Star -(23, 15), -- User 23: Data Enthusiast -(24, 5), -- User 24: Early Adopter -(25, 9), -- User 25: Team Player -(26, 2); -- User 26: Expert Reviewer - - - -INSERT INTO Feedback (userID, header, content, status) VALUES -(1, 'Great Service', 'I really appreciate the recent updates to the app.', 'In Progress'), -(2, 'Feature Request', 'Could you add a scheduling feature for tasks?', 'Implemented'), -(3, 'Bug Report', 'The app freezes when trying to generate a report.', 'In Progress'), -(4, 'Login Issue', 'Unable to reset my password using the forgot password option.', 'Rejected'), -(5, 'UI Feedback', 'The new layout is great, but the text is too small.', 'Implemented'), -(6, 'Performance Issue', 'The site becomes unresponsive during peak hours.', 'In Progress'), -(7, 'Dark Mode', 'Dark mode would improve usability at night.', 'Implemented'), -(8, 'Security Concern', 'Is there two-factor authentication available?', 'Rejected'), -(9, 'Account Feature', 'Can you provide an option to link multiple accounts?', 'In Progress'), -(10, 'Pricing Feedback', 'The pricing tiers seem unclear to new users.', 'Rejected'), -(11, 'New Feature', 'Adding analytics dashboards would be a great feature.', 'Implemented'), -(12, 'Mobile App Issue', 'The mobile app crashes when scrolling through large lists.', 'In Progress'), -(13, 'Positive Feedback', 'The team is doing a fantastic job with updates.', 'Implemented'), -(14, 'Bug in Search', 'The search function does not return relevant results.', 'In Progress'), -(15, 'User Permissions', 'Please allow admins to set custom permissions.', 'Implemented'), -(16, 'Customer Support', 'Your customer support resolved my issue quickly!', 'Rejected'), -(17, 'Feature Request', 'It would be great to have offline mode in the app.', 'Implemented'), -(18, 'Slow Loading', 'Pages take a long time to load on mobile devices.', 'In Progress'), -(19, 'API Enhancement', 'Can you add more filters to the API endpoints?', 'Rejected'), -(20, 'Email Notifications', 'The email notifications are inconsistent.', 'In Progress'), -(21, 'Dashboard Update', 'I like the new dashboard, but it feels a bit cluttered.', 'Implemented'), -(22, 'Integration Request', 'Can you integrate with XYZ service?', 'Rejected'), -(23, 'Navigation Issue', 'The navigation menu disappears on smaller screens.', 'In Progress'), -(24, 'Search Enhancement', 'Can you add autocomplete to the search bar?', 'Implemented'), -(25, 'Feature Idea', 'How about a collaborative editing feature?', 'In Progress'), -(26, 'UI Feedback', 'The color contrast is not accessible for all users.', 'Rejected'), -(27, 'Report Generation', 'Reports take too long to generate.', 'Implemented'), -(28, 'Settings Option', 'Allow users to export their settings as a file.', 'In Progress'), -(29, 'Appreciation', 'The recent updates have been excellent!', 'Implemented'), -(30, 'Feedback on Beta', 'The beta version is unstable on older devices.', 'Rejected'), -(1, 'Suggestion', 'Add a save as draft option for posts.', 'Implemented'), -(2, 'Account Settings', 'The account settings are difficult to navigate.', 'In Progress'), -(3, 'Feature Request', 'Include a timer for sessions.', 'Rejected'), -(4, 'UI Improvement', 'The text alignment on the settings page is off.', 'In Progress'), -(5, 'Server Downtime', 'The server goes down frequently in my region.', 'Implemented'), -(6, 'Password Management', 'Add a password strength indicator.', 'Rejected'), -(7, 'Onboarding', 'The onboarding process is not very user-friendly.', 'In Progress'), -(8, 'Localization', 'Can you add support for more languages?', 'Implemented'), -(9, 'Social Media', 'Integrate with popular social media platforms.', 'Rejected'), -(10, 'Billing System', 'The billing system has recurring issues.', 'In Progress'); - - - - - diff --git a/database-files/11_CoopPlatform_Data.sql b/database-files/11_CoopPlatform_Data.sql deleted file mode 100644 index de87906064..0000000000 --- a/database-files/11_CoopPlatform_Data.sql +++ /dev/null @@ -1,393 +0,0 @@ --- Use the newly created database -USE CoopPlatform; - - -INSERT INTO User (firstName, lastName, email, major, skills, interests, isAdmin, isAnalyst) VALUES -('Alice', 'Smith', 'alice.smith@example.com', 'Computer Science', 'Java, Python', 'AI, Robotics', FALSE, TRUE), -('Bob', 'Johnson', 'bob.johnson@example.com', 'Mathematics', 'R, MATLAB', 'Statistics, Data Science', FALSE, TRUE), -('Charlie', 'Brown', 'charlie.brown@example.com', 'Physics', 'C++, Fortran', 'Quantum Mechanics, Astrophysics', FALSE, FALSE), -('Diana', 'Prince', 'diana.prince@example.com', 'Electrical Engineering', 'C, Embedded Systems', 'Renewable Energy, IoT', FALSE, FALSE), -('Ethan', 'Hunt', 'ethan.hunt@example.com', 'Cybersecurity', 'Networking, Ethical Hacking', 'Digital Security, Cryptography', FALSE, TRUE), -('Fiona', 'Gallagher', 'fiona.gallagher@example.com', 'Psychology', 'SPSS, Data Analysis', 'Behavioral Studies, Neuropsychology', FALSE, FALSE), -('George', 'Michaels', 'george.michaels@example.com', 'Business', 'Excel, SQL', 'Entrepreneurship, Management', FALSE, FALSE), -('Hannah', 'Montana', 'hannah.montana@example.com', 'Music', 'Composition, Audio Editing', 'Songwriting, Producing', FALSE, FALSE), -('Ian', 'Malcolm', 'ian.malcolm@example.com', 'Biology', 'Genetics, Bioinformatics', 'Evolution, Conservation', FALSE, TRUE), -('Julia', 'Roberts', 'julia.roberts@example.com', 'Drama', 'Acting, Directing', 'Theater, Film Studies', FALSE, FALSE), -('Kevin', 'Hart', 'kevin.hart@example.com', 'Performing Arts', 'Comedy, Storytelling', 'Improv, Stand-up', FALSE, FALSE), -('Laura', 'Croft', 'laura.croft@example.com', 'Archaeology', 'Field Research, Mapping', 'Ancient Civilizations, Exploration', FALSE, TRUE), -('Michael', 'Scott', 'michael.scott@example.com', 'Business Administration', 'Leadership, Communication', 'Sales, Marketing', TRUE, FALSE), -('Nancy', 'Drew', 'nancy.drew@example.com', 'Criminology', 'Investigation, Profiling', 'Mysteries, Forensics', FALSE, FALSE), -('Oliver', 'Queen', 'oliver.queen@example.com', 'Political Science', 'Policy Analysis, Strategy', 'Social Justice, Governance', FALSE, FALSE), -('Penelope', 'Garcia', 'penelope.garcia@example.com', 'Information Systems', 'Database Management, Programming', 'Technology, Cybersecurity', FALSE, TRUE), -('Quincy', 'Jones', 'quincy.jones@example.com', 'Music', 'Arranging, Producing', 'Jazz, Classical', FALSE, FALSE), -('Rachel', 'Green', 'rachel.green@example.com', 'Fashion Design', 'Sketching, Sewing', 'Trends, Styling', FALSE, FALSE), -('Steve', 'Jobs', 'steve.jobs@example.com', 'Product Design', 'Innovation, Prototyping', 'Technology, Design Thinking', FALSE, TRUE), -('Tracy', 'Morgan', 'tracy.morgan@example.com', 'Comedy Writing', 'Humor, Screenwriting', 'Sitcoms, Stand-up', FALSE, FALSE), -('Uma', 'Thurman', 'uma.thurman@example.com', 'Film Studies', 'Directing, Editing', 'Cinema, Storytelling', FALSE, FALSE), -('Victor', 'Frankenstein', 'victor.frankenstein@example.com', 'Biotechnology', 'CRISPR, Synthetic Biology', 'Genetic Engineering, Bioethics', FALSE, TRUE), -('Will', 'Smith', 'will.smith@example.com', 'Acting', 'Acting, Producing', 'Film, Music', FALSE, FALSE), -('Xander', 'Harris', 'xander.harris@example.com', 'History', 'Archival Research, Writing', 'Medieval History, Literature', FALSE, FALSE), -('Yara', 'Greyjoy', 'yara.greyjoy@example.com', 'Marine Biology', 'Oceanography, Diving', 'Marine Conservation, Ecology', FALSE, TRUE), -('Zara', 'Larsson', 'zara.larsson@example.com', 'Music Production', 'Singing, Mixing', 'Pop Music, Performance', FALSE, FALSE), -('Adam', 'West', 'adam.west@example.com', 'Theater', 'Acting, Public Speaking', 'Drama, Performance', FALSE, FALSE), -('Bella', 'Swan', 'bella.swan@example.com', 'Literature', 'Creative Writing, Editing', 'Romance, Fiction', FALSE, FALSE), -('Chris', 'Evans', 'chris.evans@example.com', 'Film Production', 'Editing, Cinematography', 'Action, Direction', FALSE, TRUE), -('Derek', 'Shepherd', 'derek.shepherd@example.com', 'Medicine', 'Surgery, Research', 'Neurosurgery, Health Care', FALSE, FALSE), -('Evelyn', 'Salt', 'evelyn.salt@example.com', 'International Relations', 'Negotiation, Strategy', 'Conflict Resolution, Diplomacy', FALSE, FALSE), -('Finn', 'Hudson', 'finn.hudson@example.com', 'Music Education', 'Choir, Performance', 'Teaching, Vocal Training', FALSE, FALSE), -('Grace', 'Hopper', 'grace.hopper@example.com', 'Computer Science', 'Programming, Algorithms', 'Innovation, Women in Tech', TRUE, TRUE), -('Harvey', 'Specter', 'harvey.specter@example.com', 'Law', 'Litigation, Negotiation', 'Corporate Law, Strategy', FALSE, FALSE); - -INSERT INTO Companies (name, description, createdAt, updatedAt) VALUES -('TechNova Inc.', 'A leading company in AI and machine learning solutions.', '2020-05-14 12:34:56', '2022-11-01 15:45:30'), -('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.', '2021-02-20 09:22:10', '2023-05-14 10:40:20'), -('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.', '2020-09-10 14:18:20', '2023-01-27 19:34:50'), -('EcoEnergy Co.', NULL, '2020-06-01 11:45:10', '2021-12-19 16:22:10'), -#('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.', '2020-06-01 11:45:10', '2021-12-19 16:22:10'), -('BrightFuture Education', 'Providing online and in-person educational programs worldwide.', '2021-07-15 08:30:00', '2024-04-12 18:11:45'), -('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.', '2020-11-05 10:20:30', '2022-08-21 09:50:40'), -('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.', '2022-03-18 15:12:00', '2023-10-25 20:05:50'), -('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.', '2021-09-12 13:25:30', '2024-01-10 14:40:30'), -('GlobalTech Solutions', 'Delivering IT consulting and software development services.', '2021-05-25 10:50:50', '2023-07-15 17:05:20'), -('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.', '2020-12-19 14:15:45', '2022-06-30 18:25:40'), -('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.', '2020-04-10 11:10:10', '2024-03-05 10:55:00'), -('FinPro Banking', 'A financial services firm offering innovative banking solutions.', '2021-08-23 16:45:25', '2022-11-18 12:35:50'), -('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.', '2020-01-05 09:30:15', '2023-09-29 15:45:25'), -('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.', '2022-02-11 18:00:00', '2023-06-12 11:22:33'), -('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.', '2021-03-17 14:50:35', '2024-02-01 12:00:45'), -('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.', '2020-08-21 10:05:45', '2023-03-30 14:45:50'), -('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.', '2020-10-13 09:15:00', '2022-10-05 16:50:40'), -('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.', '2021-06-30 14:45:20', '2023-12-02 20:10:10'), -('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.', '2020-03-25 13:40:10', '2022-09-21 15:45:45'), -('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.', '2020-07-14 11:30:00', '2024-01-22 10:20:50'), -('Visionary Designs', 'Offering innovative and stylish interior design services.', '2021-01-10 12:15:25', '2023-05-01 09:40:30'), -('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.', '2021-04-07 14:22:30', '2023-10-15 13:45:50'), -('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.', '2020-02-19 08:45:15', '2023-07-11 17:30:20'), -('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.', '2020-11-11 12:50:45', '2024-05-20 19:50:40'), -('DataPulse Analytics', 'Helping businesses harness big data for decision-making.', '2022-01-18 10:25:00', '2023-08-30 14:55:30'), -('GreenTech Farms', 'Implementing innovative vertical farming solutions.', '2021-11-21 15:35:20', '2024-04-14 09:45:00'), -('CloudNet Systems', 'Offering cloud computing and data storage services.', '2021-10-09 17:15:45', '2023-09-03 11:05:10'), -('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.', '2020-06-08 09:45:10', '2022-05-25 18:55:40'), -('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.', '2021-07-05 13:50:50', '2024-03-19 15:20:30'), -('QuantumLeap Solutions', 'Researching quantum computing and its applications.', '2020-09-15 14:10:45', '2023-06-25 12:45:50'); - - - - -INSERT INTO Industries (name) VALUES -('Information Technology'), -('Healthcare'), -('Education'), -('Finance'), -('Automotive'), -('Biotechnology'), -('Aerospace'), -('Renewable Energy'), -('Construction'), -('Entertainment'), -('Robotics'), -('Logistics'), -('Cybersecurity'), -('Sports and Recreation'), -('Real Estate'), -('Food and Beverage'), -('Interior Design'), -('Pet Care'), -('Travel and Tourism'), -('Manufacturing'), -('Data Analytics'), -('Agriculture'), -('Cloud Computing'), -('Arts and Crafts'), -('E-commerce'), -('Quantum Computing'), -('Fashion and Apparel'), -('Gaming'), -('Pharmaceuticals'), -('Marine and Aquatic Technologies'); - - -INSERT INTO CompanyIndustry (companyID, industryID) VALUES -(1, 1), -- TechNova Inc. -> Information Technology -(1, 13), -- TechNova Inc. -> Cybersecurity -(2, 22), -- GreenFields Ltd. -> Agriculture -(2, 8), -- GreenFields Ltd. -> Renewable Energy -(3, 7), -- SkyHigh Aerospace -> Aerospace -(4, 8), -- EcoEnergy Co. -> Renewable Energy -(4, 21), -- EcoEnergy Co. -> Manufacturing -(5, 3), -- BrightFuture Education -> Education -(6, 2), -- HealthCore Pharmaceuticals -> Healthcare -(6, 30), -- HealthCore Pharmaceuticals -> Pharmaceuticals -(7, 9), -- UrbanBuilders LLC -> Construction -(8, 30), -- AquaLife Systems -> Marine and Aquatic Technologies -(9, 1), -- GlobalTech Solutions -> Information Technology -(10, 10), -- Stellar Entertainment -> Entertainment -(11, 12), -- NextGen Robotics -> Robotics -(11, 21), -- NextGen Robotics -> Manufacturing -(12, 4), -- FinPro Banking -> Finance -(13, 5), -- AutoFuture Ltd. -> Automotive -(13, 21), -- AutoFuture Ltd. -> Manufacturing -(14, 6), -- BioGenomics Inc. -> Biotechnology -(14, 30), -- BioGenomics Inc. -> Pharmaceuticals -(15, 12), -- BlueOcean Logistics -> Logistics -(16, 13), -- CyberShield Security -> Cybersecurity -(17, 14), -- Peak Performance Sports -> Sports and Recreation -(18, 9), -- EcoHomes Construction -> Construction -(18, 8), -- EcoHomes Construction -> Renewable Energy -(19, 1), -- VirtuMed Technologies -> Information Technology -(19, 3), -- VirtuMed Technologies -> Education -(20, 17), -- Gourmet World Foods -> Food and Beverage -(21, 10), -- Visionary Designs -> Interior Design -(22, 18), -- PetCare Innovations -> Pet Care -(23, 19), -- TravelSphere Ltd. -> Travel and Tourism -(24, 21), -- FusionTech Manufacturing -> Manufacturing -(25, 20), -- DataPulse Analytics -> Data Analytics -(26, 22), -- GreenTech Farms -> Agriculture -(27, 23), -- CloudNet Systems -> Cloud Computing -(28, 24), -- ArtisanCrafts Co. -> Arts and Crafts -(29, 25), -- BrightPath Logistics -> E-commerce -(30, 26); -- QuantumLeap Solutions -> Quantum Computing - -INSERT INTO Location (companyID, address, city, state_province, country) VALUES -(1, '123 Innovation Blvd', 'San Francisco', 'California', 'USA'), -(2, '456 Greenway Rd', 'Seattle', 'Washington', 'USA'), -(3, '789 SkyHigh Dr', 'Huntsville', 'Alabama', 'USA'), -(4, '321 Solar St', 'Austin', 'Texas', 'USA'), -(5, '654 Bright Ln', 'Boston', 'Massachusetts', 'USA'), -(6, '987 Pharma Ave', 'Cambridge', 'Massachusetts', 'USA'), -(7, '111 Builder Way', 'New York', 'New York', 'USA'), -(8, '222 Water Works', 'Miami', 'Florida', 'USA'), -(9, '333 Tech Plaza', 'San Jose', 'California', 'USA'), -(10, '444 Entertainment Row', 'Los Angeles', 'California', 'USA'), -(11, '555 Robotics St', 'Pittsburgh', 'Pennsylvania', 'USA'), -(12, '666 Finance Blvd', 'Chicago', 'Illinois', 'USA'), -(13, '777 Auto Ln', 'Detroit', 'Michigan', 'USA'), -(14, '888 BioTech Rd', 'San Diego', 'California', 'USA'), -(15, '999 Ocean Dr', 'Savannah', 'Georgia', 'USA'), -(16, '121 Cyber Ave', 'Austin', 'Texas', 'USA'), -(17, '131 Sports Way', 'Portland', 'Oregon', 'USA'), -(18, '141 Eco Homes Blvd', 'Denver', 'Colorado', 'USA'), -(19, '151 MedTech Dr', 'Houston', 'Texas', 'USA'), -(20, '161 Gourmet St', 'Paris', 'Île-de-France', 'France'), -(21, '171 Design Ln', 'Milan', 'Lombardy', 'Italy'), -(22, '181 PetCare Way', 'Sydney', 'New South Wales', 'Australia'), -(23, '191 Travel Blvd', 'London', 'England', 'United Kingdom'), -(24, '201 FusionTech Rd', 'Munich', 'Bavaria', 'Germany'), -(25, '211 DataPulse Ave', 'Toronto', 'Ontario', 'Canada'), -(26, '221 Green Farms Rd', 'Amsterdam', 'North Holland', 'Netherlands'), -(27, '231 CloudNet Dr', 'Dublin', 'Leinster', 'Ireland'), -(28, '241 Artisan Row', 'Kyoto', 'Kyoto Prefecture', 'Japan'), -(29, '251 BrightPath Blvd', 'Shanghai', 'Shanghai', 'China'), -(30, '261 Quantum Leap Way', 'Zurich', 'Zurich', 'Switzerland'), -(1, '271 Silicon Way', 'Palo Alto', 'California', 'USA'), -(12, '282 Green Circle', 'Vancouver', 'British Columbia', 'Canada'), -(23, '293 Spaceport Dr', 'Cape Canaveral', 'Florida', 'USA'), -(24, '304 Renewable St', 'Berlin', 'Berlin', 'Germany'), -(5, '315 BrightStar Rd', 'Oslo', 'Oslo', 'Norway'), -(6, '326 Pharma Labs', 'Hyderabad', 'Telangana', 'India'), -(27, '337 Builder Ln', 'Tokyo', 'Tokyo Prefecture', 'Japan'), -(18, '348 Aqua Center', 'Cape Town', 'Western Cape', 'South Africa'), -(19, '359 TechHub Blvd', 'Bangalore', 'Karnataka', 'India'), -(10, '370 Creative Row', 'Stockholm', 'Stockholm County', 'Sweden'), -(21, '381 Robotics Ave', 'Seoul', 'Seoul', 'South Korea'), -(30, '392 Financial Way', 'Zurich', 'Zurich', 'Switzerland'), -(23, '403 Auto Plaza', 'Stuttgart', 'Baden-Württemberg', 'Germany'), -(14, '414 Biotech Blvd', 'Tel Aviv', 'Tel Aviv District', 'Israel'), -(5, '425 Logistics Lane', 'Dubai', 'Dubai', 'United Arab Emirates'); - -INSERT INTO Role (companyID, locationID, roleName, description, skillsRequired) VALUES -(1, 1, 'Machine Learning Engineer', 'Design and implement machine learning models for real-world applications.', 'Python, TensorFlow, Data Analysis'), -(2, 2, 'Sustainability Analyst', 'Analyze and optimize sustainable farming practices.', 'Data Analysis, Agricultural Science'), -(3, 3, 'Aerospace Engineer', 'Develop advanced spacecraft and satellite systems.', 'C++, Aerodynamics, CAD'), -(4, 4, 'Renewable Energy Consultant', 'Consult on renewable energy projects and strategies.', 'Project Management, Solar Technology'), -(5, 5, 'Educational Content Developer', 'Create engaging educational materials for online learning.', 'Curriculum Design, Content Writing'), -(6, 6, 'Clinical Research Scientist', 'Conduct research on pharmaceutical treatments and solutions.', 'Pharmacology, Research Methods'), -(7, 7, 'Architectural Designer', 'Design urban structures and smart city layouts.', 'AutoCAD, Urban Planning'), -(8, 8, 'Water Systems Engineer', 'Develop innovative water purification and desalination systems.', 'Hydraulics, System Design'), -(9, 9, 'Software Developer', 'Build scalable software solutions for clients.', 'Java, SQL, Cloud Platforms'), -(10, 10, 'Video Producer', 'Produce and manage video content for global distribution.', 'Adobe Premiere, Cinematography'), -(11, 11, 'Robotics Engineer', 'Develop robotics solutions for industrial applications.', 'Python, Robotics Frameworks'), -(12, 12, 'Financial Analyst', 'Analyze financial data to provide strategic advice.', 'Excel, Financial Modeling'), -(13, 13, 'Automotive Engineer', 'Design and test autonomous vehicle systems.', 'Matlab, Simulink, AI'), -(14, 14, 'Biotechnology Researcher', 'Conduct research in genetic engineering and biotechnology.', 'CRISPR, Lab Techniques'), -(15, 15, 'Logistics Manager', 'Oversee and optimize supply chain operations.', 'Supply Chain Management, SAP'), -(16, 16, 'Cybersecurity Specialist', 'Protect systems from cyber threats and vulnerabilities.', 'Penetration Testing, Network Security'), -(17, 17, 'Sports Equipment Designer', 'Design high-performance sports equipment.', 'Material Science, CAD'), -(18, 18, 'Eco-Friendly Construction Manager', 'Lead eco-friendly building projects.', 'Project Management, Green Building Standards'), -(19, 19, 'Virtual Reality Developer', 'Develop VR applications for medical training.', 'Unity, C#, 3D Modeling'), -(20, 20, 'Food Product Manager', 'Manage and oversee the development of gourmet food products.', 'Food Science, Marketing'), -(21, 21, 'Interior Designer', 'Create innovative and stylish interior designs.', 'Sketching, 3D Rendering'), -(22, 22, 'Veterinary Product Specialist', 'Develop and promote veterinary products.', 'Animal Science, Product Development'), -(23, 23, 'Tour Guide Manager', 'Coordinate and manage unique travel experiences.', 'Hospitality Management, Customer Service'), -(24, 24, 'Manufacturing Process Engineer', 'Optimize manufacturing processes and workflows.', 'Process Design, Lean Manufacturing'), -(25, 25, 'Data Scientist', 'Analyze big data for actionable insights.', 'Python, Machine Learning, Data Visualization'), -(26, 26, 'Agricultural Engineer', 'Implement innovative agricultural technologies.', 'Mechanical Engineering, Agricultural Systems'), -(27, 27, 'Cloud Infrastructure Engineer', 'Manage and deploy cloud-based solutions.', 'AWS, Kubernetes, Networking'), -(28, 28, 'Artisan Product Designer', 'Design and promote handcrafted artisan products.', 'Creativity, Marketing'), -(29, 29, 'E-commerce Operations Manager', 'Manage e-commerce logistics and operations.', 'Inventory Management, Analytics'), -(30, 30, 'Quantum Computing Researcher', 'Research and develop quantum computing applications.', 'Quantum Mechanics, Algorithms'); - -INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES -(1, 1, '2024-01-01 10:00:00', 'Experience', 'Great Experience as an ML Engineer', 'I had a fantastic experience working as a Machine Learning Engineer at TechNova Inc. Learned a lot about AI.', 150, 35, FALSE), -(2, 2, '2024-01-05 15:30:00', 'Feedback', 'Improved Sustainability Practices', 'The company is making significant strides in sustainability, but communication needs improvement.', 100, 20, FALSE), -(3, 3, '2024-01-10 09:45:00', 'Review', 'Exciting Role in Aerospace', 'Working on cutting-edge technology was inspiring. Would recommend it to any aspiring engineer.', 200, 50, FALSE), -(4, 4, '2024-01-15 14:20:00', 'Insight', 'Great Opportunity in Renewable Energy', 'A rewarding experience with excellent leadership and vision.', 120, 25, FALSE), -(5, 5, '2024-01-20 11:10:00', 'Experience', 'Rewarding Work Environment', 'Collaborative culture and strong focus on education made my role enjoyable.', 90, 15, FALSE), -(6, 6, '2024-01-25 17:00:00', 'Feedback', 'Cutting-Edge Research', 'Involved in exciting research but workload was quite heavy.', 140, 30, FALSE), -(7, 7, '2024-02-01 08:00:00', 'Review', 'Urban Development at Its Best', 'Loved working on innovative projects for smart cities.', 85, 10, FALSE), -(8, 8, '2024-02-05 10:30:00', 'Insight', 'Advancing Water Purification', 'Meaningful work but limited opportunities for growth.', 70, 12, FALSE), -(9, 9, '2024-02-10 13:15:00', 'Experience', 'Dynamic Work Environment', 'Fast-paced and challenging, great place for software enthusiasts.', 180, 40, FALSE), -(10, 10, '2024-02-15 16:45:00', 'Feedback', 'Creative and Supportive', 'Perfect workplace for creative professionals.', 75, 18, FALSE), -(11, 11, '2024-02-20 19:20:00', 'Review', 'Robotics Projects Worth Pursuing', 'Exciting projects but management needs improvement.', 95, 20, FALSE), -(12, 12, '2024-02-25 07:30:00', 'Insight', 'Great Start for Financial Analysts', 'Supportive team and ample learning opportunities.', 105, 22, FALSE), -(13, 13, '2024-03-01 11:50:00', 'Experience', 'Innovative Role in Automotive', 'Hands-on experience with cutting-edge technologies.', 130, 35, FALSE), -(14, 14, '2024-03-05 09:40:00', 'Feedback', 'Inspiring Research Environment', 'Focus on innovation, but better work-life balance needed.', 165, 28, FALSE), -(15, 15, '2024-03-10 12:25:00', 'Review', 'Streamlined Logistics Management', 'Efficient processes and a dynamic team.', 80, 14, FALSE), -(16, 16, '2024-03-15 14:00:00', 'Insight', 'Top-notch Cybersecurity Expertise', 'Fantastic workplace for security professionals.', 200, 50, FALSE), -(17, 17, '2024-03-20 15:30:00', 'Experience', 'Challenging Sports Equipment Design', 'Opportunity to innovate, but tight deadlines.', 60, 10, FALSE), -(18, 18, '2024-03-25 16:45:00', 'Feedback', 'Sustainable and Collaborative', 'Loved the eco-friendly approach and teamwork.', 95, 25, FALSE), -(19, 19, '2024-03-30 10:10:00', 'Review', 'Immersive VR Development', 'Great exposure to VR development, but lacked mentorship.', 120, 18, FALSE), -(20, 20, '2024-04-01 13:00:00', 'Insight', 'Delicious Career Growth', 'Enjoyed working on gourmet food projects.', 80, 16, FALSE), -(21, 21, '2024-04-05 14:30:00', 'Experience', 'Creative Interior Design Projects', 'Amazing projects but needs better client communication.', 110, 20, FALSE), -(22, 22, '2024-04-10 09:15:00', 'Feedback', 'Innovative Pet Products', 'Great workplace with a fun and collaborative culture.', 90, 22, FALSE), -(23, 23, '2024-04-15 10:45:00', 'Review', 'Rewarding Travel Role', 'TravelSphere provides ample learning opportunities.', 115, 18, FALSE), -(24, 24, '2024-04-20 11:30:00', 'Insight', 'Streamlined Manufacturing Process', 'High-tech projects but long hours.', 130, 24, FALSE), -(25, 25, '2024-04-25 16:00:00', 'Experience', 'Data-Driven Insights', 'DataPulse offers cutting-edge analytics projects.', 170, 40, FALSE), -(26, 26, '2024-05-01 09:40:00', 'Feedback', 'Smart Agricultural Practices', 'Good place to grow for agricultural engineers.', 140, 35, FALSE), -(27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), -(28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), -(29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), -(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE); - - -INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagged) VALUES -(1, 2, NULL, 'This sounds like a fantastic experience! Thanks for sharing.', 10, FALSE), -(1, 3, 1, 'Absolutely agree! I had a similar experience.', 5, FALSE), -(2, 4, NULL, 'Do you think the communication issue is company-wide?', 8, FALSE), -(2, 1, 4, 'Yes, I think it varies by team, but it’s something to improve.', 6, FALSE), -(3, 5, NULL, 'Aerospace is such an exciting field. How was the workload?', 12, FALSE), -(4, 6, NULL, 'I’ve been considering applying here. Any tips for getting in?', 15, FALSE), -(4, 2, 6, 'Focus on renewable energy projects in your portfolio.', 7, FALSE), -(5, 7, NULL, 'I love collaborative environments. Sounds like a great role.', 4, FALSE), -(6, 8, NULL, 'Heavy workloads can be tough. Was the management supportive?', 9, FALSE), -(6, 9, 8, 'They were supportive but often stretched thin.', 3, FALSE), -(7, 10, NULL, 'Smart cities are the future. How innovative were the projects?', 13, FALSE), -(8, 11, NULL, 'What kind of growth opportunities were you hoping for?', 6, FALSE), -(8, 3, 11, 'Leadership roles or cross-functional projects.', 4, FALSE), -(9, 12, NULL, 'Tech companies often have dynamic environments. Did you feel valued?', 11, FALSE), -(10, 13, NULL, 'Supportive workplaces are so important for creatives.', 8, FALSE), -(11, 14, NULL, 'Robotics is fascinating! What kind of robots did you work on?', 14, FALSE), -(11, 15, 14, 'Mostly industrial robots for manufacturing.', 7, FALSE), -(12, 16, NULL, 'Finance is challenging. Did you have a good team?', 10, FALSE), -(13, 17, NULL, 'I’d love to work on autonomous vehicles. Any advice?', 18, FALSE), -(14, 18, NULL, 'How innovative was the genetic research you were involved in?', 20, FALSE), -(14, 19, 18, 'Very cutting-edge, especially in CRISPR technology.', 12, FALSE), -(15, 20, NULL, 'Efficient logistics management is key to success.', 9, FALSE), -(16, 21, NULL, 'What kind of tools were used for cybersecurity?', 11, FALSE), -(16, 22, 21, 'Mostly Splunk, Wireshark, and custom tools.', 5, FALSE), -(17, 23, NULL, 'Tight deadlines can be tough. How was the work-life balance?', 7, FALSE), -(18, 24, NULL, 'Eco-friendly construction is inspiring. What projects stood out?', 14, FALSE), -(19, 25, NULL, 'VR development is fascinating. What applications did you focus on?', 17, FALSE), -(19, 26, 25, 'Medical training simulations. Very impactful.', 10, FALSE), -(20, 27, NULL, 'Gourmet food development sounds interesting! How creative was it?', 8, FALSE), -(21, 28, NULL, 'Interior design is so rewarding. What was your favorite project?', 13, FALSE); - - -INSERT INTO Badges (badgeName) VALUES -('Top Contributor'), -('Expert Reviewer'), -('Helpful Commenter'), -('Insightful Reviewer'), -('Early Adopter'), -('Collaboration Champion'), -('Creative Thinker'), -('Innovation Advocate'), -('Team Player'), -('Knowledge Sharer'), -('Problem Solver'), -('Critical Thinker'), -('Community Builder'), -('Leadership Star'), -('Data Enthusiast'); - - -INSERT INTO UserBadges (userID, badgeID) VALUES -(1, 1), -- User 1: Top Contributor -(1, 2), -- User 1: Expert Reviewer -(2, 3), -- User 2: Helpful Commenter -(2, 4), -- User 2: Insightful Reviewer -(3, 5), -- User 3: Early Adopter -(4, 6), -- User 4: Collaboration Champion -(4, 7), -- User 4: Creative Thinker -(5, 8), -- User 5: Innovation Advocate -(6, 9), -- User 6: Team Player -(6, 10), -- User 6: Knowledge Sharer -(7, 11), -- User 7: Problem Solver -(8, 12), -- User 8: Critical Thinker -(9, 13), -- User 9: Community Builder -(10, 14), -- User 10: Leadership Star -(11, 15), -- User 11: Data Enthusiast -(12, 1), -- User 12: Top Contributor -(13, 4), -- User 13: Insightful Reviewer -(14, 6), -- User 14: Collaboration Champion -(15, 7), -- User 15: Creative Thinker -(16, 8), -- User 16: Innovation Advocate -(17, 3), -- User 17: Helpful Commenter -(18, 10), -- User 18: Knowledge Sharer -(19, 11), -- User 19: Problem Solver -(20, 12), -- User 20: Critical Thinker -(21, 13), -- User 21: Community Builder -(22, 14), -- User 22: Leadership Star -(23, 15), -- User 23: Data Enthusiast -(24, 5), -- User 24: Early Adopter -(25, 9), -- User 25: Team Player -(26, 2); -- User 26: Expert Reviewer - - - -INSERT INTO Feedback (userID, header, content, status) VALUES -(1, 'Great Service', 'I really appreciate the recent updates to the app.', 'In Progress'), -(2, 'Feature Request', 'Could you add a scheduling feature for tasks?', 'Implemented'), -(3, 'Bug Report', 'The app freezes when trying to generate a report.', 'In Progress'), -(4, 'Login Issue', 'Unable to reset my password using the forgot password option.', 'Rejected'), -(5, 'UI Feedback', 'The new layout is great, but the text is too small.', 'Implemented'), -(6, 'Performance Issue', 'The site becomes unresponsive during peak hours.', 'In Progress'), -(7, 'Dark Mode', 'Dark mode would improve usability at night.', 'Implemented'), -(8, 'Security Concern', 'Is there two-factor authentication available?', 'Rejected'), -(9, 'Account Feature', 'Can you provide an option to link multiple accounts?', 'In Progress'), -(10, 'Pricing Feedback', 'The pricing tiers seem unclear to new users.', 'Rejected'), -(11, 'New Feature', 'Adding analytics dashboards would be a great feature.', 'Implemented'), -(12, 'Mobile App Issue', 'The mobile app crashes when scrolling through large lists.', 'In Progress'), -(13, 'Positive Feedback', 'The team is doing a fantastic job with updates.', 'Implemented'), -(14, 'Bug in Search', 'The search function does not return relevant results.', 'In Progress'), -(15, 'User Permissions', 'Please allow admins to set custom permissions.', 'Implemented'), -(16, 'Customer Support', 'Your customer support resolved my issue quickly!', 'Rejected'), -(17, 'Feature Request', 'It would be great to have offline mode in the app.', 'Implemented'), -(18, 'Slow Loading', 'Pages take a long time to load on mobile devices.', 'In Progress'), -(19, 'API Enhancement', 'Can you add more filters to the API endpoints?', 'Rejected'), -(20, 'Email Notifications', 'The email notifications are inconsistent.', 'In Progress'), -(21, 'Dashboard Update', 'I like the new dashboard, but it feels a bit cluttered.', 'Implemented'), -(22, 'Integration Request', 'Can you integrate with XYZ service?', 'Rejected'), -(23, 'Navigation Issue', 'The navigation menu disappears on smaller screens.', 'In Progress'), -(24, 'Search Enhancement', 'Can you add autocomplete to the search bar?', 'Implemented'), -(25, 'Feature Idea', 'How about a collaborative editing feature?', 'In Progress'), -(26, 'UI Feedback', 'The color contrast is not accessible for all users.', 'Rejected'), -(27, 'Report Generation', 'Reports take too long to generate.', 'Implemented'), -(28, 'Settings Option', 'Allow users to export their settings as a file.', 'In Progress'), -(29, 'Appreciation', 'The recent updates have been excellent!', 'Implemented'), -(30, 'Feedback on Beta', 'The beta version is unstable on older devices.', 'Rejected'), -(1, 'Suggestion', 'Add a save as draft option for posts.', 'Implemented'), -(2, 'Account Settings', 'The account settings are difficult to navigate.', 'In Progress'), -(3, 'Feature Request', 'Include a timer for sessions.', 'Rejected'), -(4, 'UI Improvement', 'The text alignment on the settings page is off.', 'In Progress'), -(5, 'Server Downtime', 'The server goes down frequently in my region.', 'Implemented'), -(6, 'Password Management', 'Add a password strength indicator.', 'Rejected'), -(7, 'Onboarding', 'The onboarding process is not very user-friendly.', 'In Progress'), -(8, 'Localization', 'Can you add support for more languages?', 'Implemented'), -(9, 'Social Media', 'Integrate with popular social media platforms.', 'Rejected'), -(10, 'Billing System', 'The billing system has recurring issues.', 'In Progress'); - - - - - diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index 2a558aef85..a7636767f1 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -382,5 +382,36 @@ INSERT INTO Feedback (userID, header, content) VALUES (5, 'Content Curation', 'Curating high-quality reviews or featuring top contributors could inspire others.'); +INSERT INTO InterviewReports (roleID, userID, interviewDate, difficultyLevel, notes, tips) VALUES +(1, 1, '2024-08-10', 'Hard', 'The interview covered advanced ML algorithms, including neural networks and reinforcement learning.', 'Review basic ML concepts and focus on model deployment strategies.'), +(2, 2, '2024-08-12', 'Medium', 'The interview involved sustainability case studies and analysis of environmental impact reports.', 'Be prepared to discuss recent advancements in sustainable farming technologies.'), +(3, 3, '2024-08-15', 'Hard', 'The interview asked about satellite design and aerodynamics, with technical problems related to spacecraft dynamics.', 'Study advanced aerodynamics principles and spacecraft systems.'), +(4, 4, '2024-08-18', 'Medium', 'The interview was more focused on renewable energy trends and project management for large-scale solar projects.', 'Know the basics of solar energy and project lifecycle management.'), +(5, 5, '2024-08-20', 'Easy', 'The interview was based on content development strategies, including ideas for online learning materials.', 'Make sure you have examples of your previous educational content work ready.'), +(6, 6, '2024-08-22', 'Medium', 'The interview included questions about clinical trials and statistical methods for analyzing treatment data.', 'Brush up on research methods and the latest trends in clinical trials.'), +(7, 7, '2024-08-25', 'Medium', 'The interview discussed architectural design, focusing on urban planning and sustainable building materials.', 'Familiarize yourself with new urban design trends and eco-friendly materials.'), +(8, 8, '2024-08-28', 'Hard', 'The interview included technical questions on water purification systems and hydraulics.', 'Study advanced water treatment technologies and system design principles.'), +(9, 9, '2024-09-01', 'Medium', 'The interview was about designing scalable software and understanding cloud architecture.', 'Prepare to talk about cloud computing and distributed systems in depth.'), +(10, 10, '2024-09-03', 'Easy', 'The interview focused on content creation and video production techniques for digital platforms.', 'Bring a portfolio of your previous video work and show your creative process.'), +(11, 11, '2024-09-06', 'Medium', 'The interview asked questions about robotics engineering and automating industrial processes.', 'Review robotics programming and automation techniques.'), +(12, 12, '2024-09-09', 'Medium', 'The interview involved questions on financial analysis and modeling techniques for business decision-making.', 'Practice financial modeling using Excel and understand different valuation techniques.'), +(13, 13, '2024-09-12', 'Hard', 'The interview asked about autonomous vehicle technologies and control systems for self-driving cars.', 'Prepare to discuss the latest advancements in autonomous driving technologies.'), +(14, 14, '2024-09-14', 'Medium', 'The interview focused on biotechnology research, specifically CRISPR technology and genetic engineering.', 'Review current CRISPR techniques and its applications in genetic modification.'), +(15, 15, '2024-09-17', 'Medium', 'The interview covered logistics and supply chain optimization methods, with a focus on SAP systems.', 'Study supply chain management practices and how SAP is used for optimization.'), +(16, 16, '2024-09-20', 'Hard', 'The interview included cybersecurity scenarios, focusing on penetration testing and system vulnerabilities.', 'Review network security principles and practice penetration testing techniques.'), +(17, 17, '2024-09-23', 'Medium', 'The interview discussed the design of sports equipment and material science for manufacturing high-performance gear.', 'Prepare to talk about materials used in sports equipment and performance enhancement.'), +(18, 18, '2024-09-26', 'Medium', 'The interview focused on green building standards and managing eco-friendly construction projects.', 'Be prepared to discuss LEED certifications and green construction techniques.'), +(19, 19, '2024-09-29', 'Medium', 'The interview included questions on developing VR applications, focusing on medical simulations and training programs.', 'Study the latest trends in virtual reality development, especially in medical applications.'), +(20, 20, '2024-10-01', 'Medium', 'The interview asked about managing food product development, including market trends and production processes.', 'Review trends in food science and how to launch a successful product line.'), +(21, 21, '2024-10-04', 'Easy', 'The interview focused on interior design concepts, creative design techniques, and project execution.', 'Bring a portfolio showcasing your interior design work and creative process.'), +(22, 22, '2024-10-06', 'Medium', 'The interview covered the development and promotion of veterinary products, with a focus on regulatory compliance.', 'Know the latest trends in veterinary products and regulatory requirements.'), +(23, 23, '2024-10-09', 'Easy', 'The interview was focused on tourism management, including customer service techniques and logistics planning for tours.', 'Prepare examples of your customer service experience in the hospitality industry.'), +(24, 24, '2024-10-12', 'Medium', 'The interview discussed optimizing manufacturing processes, including lean manufacturing principles and process design.', 'Familiarize yourself with lean principles and how they apply to manufacturing workflows.'), +(25, 25, '2024-10-15', 'Hard', 'The interview asked about advanced data analysis techniques, including machine learning models for data-driven decision-making.', 'Prepare to discuss your experience with machine learning and data visualization.'), +(26, 26, '2024-10-18', 'Medium', 'The interview focused on agricultural engineering, specifically the implementation of new technologies in farming.', 'Review the latest agricultural technologies and mechanical engineering concepts.'), +(27, 27, '2024-10-21', 'Hard', 'The interview covered cloud infrastructure management, focusing on AWS and Kubernetes for scalable deployments.', 'Brush up on AWS services and Kubernetes for container orchestration.'), +(28, 28, '2024-10-24', 'Easy', 'The interview was about artisan product design, with a focus on creative strategies and marketing methods.', 'Prepare examples of your handmade products and how you market them.'), +(29, 29, '2024-10-27', 'Medium', 'The interview focused on e-commerce logistics, including inventory management and analytics for improving operations.', 'Study e-commerce best practices and how to use data to improve logistics.'), +(30, 30, '2024-10-30', 'Hard', 'The interview was about quantum computing research, with a focus on algorithms and real-world applications of quantum theory.', 'Prepare to discuss quantum mechanics and how quantum computing can be applied in real-world scenarios.'); From 5663a650dc37828373763a207b2d0fe8eea07759 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 22:05:06 -0500 Subject: [PATCH 33/75] Got rid of interwiew reports --- database-files/10_coopPlatformDB.sql | 12 --------- database-files/12_CoopPlatform_Data.sql | 34 ------------------------- 2 files changed, 46 deletions(-) diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index 9f6cb621d9..e780f0955c 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -136,18 +136,6 @@ CREATE TABLE IF NOT EXISTS Feedback ( FOREIGN KEY (userID) REFERENCES User(userID) ); --- Create InterviewReports table -CREATE TABLE IF NOT EXISTS InterviewReports ( - reportID INT AUTO_INCREMENT PRIMARY KEY, - roleID INT, - userID INT, - interviewDate DATE, - difficultyLevel VARCHAR(50), - tips TEXT, - FOREIGN KEY (roleID) REFERENCES Role(roleID), - FOREIGN KEY (userID) REFERENCES User(userID) -); - diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index a7636767f1..30c5a01ea8 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -381,37 +381,3 @@ INSERT INTO Feedback (userID, header, content) VALUES (4, 'Mentorship Program', 'A mentorship program linking experienced users with newcomers would be valuable.'), (5, 'Content Curation', 'Curating high-quality reviews or featuring top contributors could inspire others.'); - -INSERT INTO InterviewReports (roleID, userID, interviewDate, difficultyLevel, notes, tips) VALUES -(1, 1, '2024-08-10', 'Hard', 'The interview covered advanced ML algorithms, including neural networks and reinforcement learning.', 'Review basic ML concepts and focus on model deployment strategies.'), -(2, 2, '2024-08-12', 'Medium', 'The interview involved sustainability case studies and analysis of environmental impact reports.', 'Be prepared to discuss recent advancements in sustainable farming technologies.'), -(3, 3, '2024-08-15', 'Hard', 'The interview asked about satellite design and aerodynamics, with technical problems related to spacecraft dynamics.', 'Study advanced aerodynamics principles and spacecraft systems.'), -(4, 4, '2024-08-18', 'Medium', 'The interview was more focused on renewable energy trends and project management for large-scale solar projects.', 'Know the basics of solar energy and project lifecycle management.'), -(5, 5, '2024-08-20', 'Easy', 'The interview was based on content development strategies, including ideas for online learning materials.', 'Make sure you have examples of your previous educational content work ready.'), -(6, 6, '2024-08-22', 'Medium', 'The interview included questions about clinical trials and statistical methods for analyzing treatment data.', 'Brush up on research methods and the latest trends in clinical trials.'), -(7, 7, '2024-08-25', 'Medium', 'The interview discussed architectural design, focusing on urban planning and sustainable building materials.', 'Familiarize yourself with new urban design trends and eco-friendly materials.'), -(8, 8, '2024-08-28', 'Hard', 'The interview included technical questions on water purification systems and hydraulics.', 'Study advanced water treatment technologies and system design principles.'), -(9, 9, '2024-09-01', 'Medium', 'The interview was about designing scalable software and understanding cloud architecture.', 'Prepare to talk about cloud computing and distributed systems in depth.'), -(10, 10, '2024-09-03', 'Easy', 'The interview focused on content creation and video production techniques for digital platforms.', 'Bring a portfolio of your previous video work and show your creative process.'), -(11, 11, '2024-09-06', 'Medium', 'The interview asked questions about robotics engineering and automating industrial processes.', 'Review robotics programming and automation techniques.'), -(12, 12, '2024-09-09', 'Medium', 'The interview involved questions on financial analysis and modeling techniques for business decision-making.', 'Practice financial modeling using Excel and understand different valuation techniques.'), -(13, 13, '2024-09-12', 'Hard', 'The interview asked about autonomous vehicle technologies and control systems for self-driving cars.', 'Prepare to discuss the latest advancements in autonomous driving technologies.'), -(14, 14, '2024-09-14', 'Medium', 'The interview focused on biotechnology research, specifically CRISPR technology and genetic engineering.', 'Review current CRISPR techniques and its applications in genetic modification.'), -(15, 15, '2024-09-17', 'Medium', 'The interview covered logistics and supply chain optimization methods, with a focus on SAP systems.', 'Study supply chain management practices and how SAP is used for optimization.'), -(16, 16, '2024-09-20', 'Hard', 'The interview included cybersecurity scenarios, focusing on penetration testing and system vulnerabilities.', 'Review network security principles and practice penetration testing techniques.'), -(17, 17, '2024-09-23', 'Medium', 'The interview discussed the design of sports equipment and material science for manufacturing high-performance gear.', 'Prepare to talk about materials used in sports equipment and performance enhancement.'), -(18, 18, '2024-09-26', 'Medium', 'The interview focused on green building standards and managing eco-friendly construction projects.', 'Be prepared to discuss LEED certifications and green construction techniques.'), -(19, 19, '2024-09-29', 'Medium', 'The interview included questions on developing VR applications, focusing on medical simulations and training programs.', 'Study the latest trends in virtual reality development, especially in medical applications.'), -(20, 20, '2024-10-01', 'Medium', 'The interview asked about managing food product development, including market trends and production processes.', 'Review trends in food science and how to launch a successful product line.'), -(21, 21, '2024-10-04', 'Easy', 'The interview focused on interior design concepts, creative design techniques, and project execution.', 'Bring a portfolio showcasing your interior design work and creative process.'), -(22, 22, '2024-10-06', 'Medium', 'The interview covered the development and promotion of veterinary products, with a focus on regulatory compliance.', 'Know the latest trends in veterinary products and regulatory requirements.'), -(23, 23, '2024-10-09', 'Easy', 'The interview was focused on tourism management, including customer service techniques and logistics planning for tours.', 'Prepare examples of your customer service experience in the hospitality industry.'), -(24, 24, '2024-10-12', 'Medium', 'The interview discussed optimizing manufacturing processes, including lean manufacturing principles and process design.', 'Familiarize yourself with lean principles and how they apply to manufacturing workflows.'), -(25, 25, '2024-10-15', 'Hard', 'The interview asked about advanced data analysis techniques, including machine learning models for data-driven decision-making.', 'Prepare to discuss your experience with machine learning and data visualization.'), -(26, 26, '2024-10-18', 'Medium', 'The interview focused on agricultural engineering, specifically the implementation of new technologies in farming.', 'Review the latest agricultural technologies and mechanical engineering concepts.'), -(27, 27, '2024-10-21', 'Hard', 'The interview covered cloud infrastructure management, focusing on AWS and Kubernetes for scalable deployments.', 'Brush up on AWS services and Kubernetes for container orchestration.'), -(28, 28, '2024-10-24', 'Easy', 'The interview was about artisan product design, with a focus on creative strategies and marketing methods.', 'Prepare examples of your handmade products and how you market them.'), -(29, 29, '2024-10-27', 'Medium', 'The interview focused on e-commerce logistics, including inventory management and analytics for improving operations.', 'Study e-commerce best practices and how to use data to improve logistics.'), -(30, 30, '2024-10-30', 'Hard', 'The interview was about quantum computing research, with a focus on algorithms and real-world applications of quantum theory.', 'Prepare to discuss quantum mechanics and how quantum computing can be applied in real-world scenarios.'); - - From 33c66d3944826188753ee8518ba00fb503c4ab4a Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 22:11:20 -0500 Subject: [PATCH 34/75] Reviews display comments under them. Also added ability to edit reviews --- api/backend/reviews/reviews_routes.py | 50 ++++++++++++++ app/src/pages/2002_My_Reviews.py | 87 ++++++++++++++++++++++--- app/src/pages/200_CoOp_Reviewer_Home.py | 2 +- 3 files changed, 128 insertions(+), 11 deletions(-) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index 19539f9937..be106866bd 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -83,6 +83,56 @@ def get_product_detail (id): response.status_code = 200 return response +@reviews.route('/commentsByReview/', methods=['GET']) +def get_comments_by_review(reviewID): + query = f''' + SELECT + c.commentID, + c.userID, + c.parentCommentID, + c.createdAt, + c.content, + c.likes + FROM + Comments c + WHERE + c.reviewID = {str(reviewID)} + ORDER BY + c.createdAt ASC; + ''' + + # Get the database connection, execute the query, and + # fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +@reviews.route('/updateReview', methods=['PUT']) +def update_review(): + data = request.get_json() + + reviewID = data.get('reviewID') + heading = data.get('heading') + content = data.get('content') + reviewType = data.get('reviewType') + + query = ''' + UPDATE Reviews + SET heading = %s, content = %s, reviewType = %s + WHERE reviewID = %s; + ''' + + cursor = db.get_db().cursor() + cursor.execute(query, (heading, content, reviewType, reviewID)) + db.get_db().commit() + + response = make_response(jsonify({"message": "Review updated successfully"})) + response.status_code = 200 + return response #------------------------------------------------------------ # Get all the products from the database, package them up, diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index 4924391578..dc423ce843 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -1,24 +1,91 @@ import logging -logger = logging.getLogger(__name__) import pandas as pd import streamlit as st from streamlit_extras.app_logo import add_logo -import world_bank_data as wb -import matplotlib.pyplot as plt -import numpy as np +import requests import plotly.express as px from modules.nav import SideBarLinks -import requests + +# Initialize logger +logger = logging.getLogger(__name__) # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() -# set the header of the page +# Set the header of the page st.header('My Reviews') -# You can access the session state to make a more customized/personalized app experience -st.write(f"### Hi, {st.session_state['first_name']}.") +# Display personalized greeting +st.write(f"### Hi, {st.session_state['first_name']}!") + +# Fetch the user's reviews +try: + response = requests.get(f'http://api:4000/r/reviewsByUser/{st.session_state["id"]}') + response.raise_for_status() + reviews = response.json() +except requests.exceptions.RequestException as e: + st.error(f"Failed to fetch reviews: {e}") + reviews = [] + +# Function to fetch comments for a review +def fetch_comments(review_id): + try: + response = requests.get(f"http://api:4000/r/commentsByReview/{review_id}") + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + logger.error(f"Failed to fetch comments for review {review_id}: {e}") + return [] + +# If there are reviews, display them +if reviews: + st.subheader("Your Reviews") + for review in reviews: + with st.container(): + # Display review details + st.markdown(f"### {review['heading']} ({review['reviewType']})") + st.markdown(f"**Published At:** {review['publishedAt']}") + st.markdown(f"**Views:** {review['views']} | **Likes:** {review['likes']}") + st.markdown(f"**Content:** {review['content']}") + + # Fetch and display comments + comments = fetch_comments(review['reviewID']) + st.markdown("#### Comments:") + if comments: + for comment in comments: + st.markdown(f"- **User {comment['userID']}**: {comment['content']} (Likes: {comment['likes']})") + else: + st.markdown("*No comments yet.*") + + # Display the edit button + if st.button(f"Edit Review", review['reviewID']): + # If the button is clicked, show the edit form + with st.form(key=f'edit_review_{review["reviewID"]}'): + st.subheader("Edit this Review") + + # Pre-fill the form with the current review details + new_heading = st.text_input("Heading", value=review["heading"]) + new_content = st.text_area("Content", value=review["content"]) + new_review_type = st.selectbox("Review Type", ["Experience", "Feedback", "Other"], index=["Experience", "Feedback", "Other"].index(review["reviewType"])) + + submit_button = st.form_submit_button(label="Update Review") + + # Handle form submission + if submit_button: + update_review_data = { + "reviewID": review["reviewID"], + "heading": new_heading, + "content": new_content, + "reviewType": new_review_type + } -results = requests.get(f'http://api:4000/r/reviewsByUser/{st.session_state["id"]}').json() -st.dataframe(results) + try: + update_response = requests.put(f'http://api:4000/r/updateReview', json=update_review_data) + update_response.raise_for_status() + st.success("Review updated successfully!") + except requests.exceptions.RequestException as e: + st.error(f"Failed to update review: {e}") + st.markdown("---") +else: + st.info("No reviews found. Start by adding your first review!") diff --git a/app/src/pages/200_CoOp_Reviewer_Home.py b/app/src/pages/200_CoOp_Reviewer_Home.py index cdef5a34f1..2cd4bb10f2 100644 --- a/app/src/pages/200_CoOp_Reviewer_Home.py +++ b/app/src/pages/200_CoOp_Reviewer_Home.py @@ -8,7 +8,7 @@ # Show appropriate sidebar links for the role of the currently logged in user SideBarLinks() -st.title(f"Welcome Co-op searcher, {st.session_state['first_name']}.") +st.title(f"Welcome Co-op reviewer, {st.session_state['first_name']}.") st.write('') st.write('') st.write('### What would you like to do today?') From 47f85de8ca2cca4d55ef6dd4a5e62262734067c6 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 22:15:37 -0500 Subject: [PATCH 35/75] Debugging http error --- api/.env | 2 +- app/src/pages/1001_Company_Position_Reviews.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/.env b/api/.env index dbe6e921f6..fcb5a4bddb 100644 --- a/api/.env +++ b/api/.env @@ -3,4 +3,4 @@ DB_USER=root DB_HOST=db DB_PORT=3306 DB_NAME=CoopPlatform -MYSQL_ROOT_PASSWORD=CoopCrazyS3 +MYSQL_ROOT_PASSWORD=password diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index abf1a180bd..2beef1ba30 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -13,7 +13,7 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -results = requests.get(f'http://api:4000/s/companiesWithReviews').json() +results = requests.get('http://api:4000/s/companiesWithReviews').json() # Extract company names into a list company_names = [item["CompanyName"] for item in results] From 0654d631846a7f6f7c5c196844295a95bf491b47 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 22:19:16 -0500 Subject: [PATCH 36/75] Feedback routes --- api/backend/feedback/feedback_routes.py | 76 +++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/api/backend/feedback/feedback_routes.py b/api/backend/feedback/feedback_routes.py index e69de29bb2..a2bfdd5ebf 100644 --- a/api/backend/feedback/feedback_routes.py +++ b/api/backend/feedback/feedback_routes.py @@ -0,0 +1,76 @@ +######################################################## +# Feedback blueprint of endpoints +######################################################## +from flask import Blueprint +from flask import request +from flask import jsonify +from flask import make_response +from flask import current_app +from backend.db_connection import db +from backend.ml_models.model01 import predict + +#------------------------------------------------------------ +# Create a new Blueprint object, which is a collection of +# routes. +feedback = Blueprint('feedback', __name__) + + +#------------------------------------------------------------ +# Get all feedback from the system +@feedback.route('/feedback', methods=['GET']) +def get_feedback(): + try: + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT feedbackID, userID, timestamp, header, content, status + FROM Feedback; + ''') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + + except Exception as e: + current_app.logger.error(f"Error fetching feedback: {e}") + return {"error": "An error occurred while fetching feedback"}, 500 + + +@feedback.route('/feedback', methods=['PUT']) +def update_status(): + current_app.logger.info('PUT /feedback route') + try: + feedback_info = request.json + + if 'feedbackID' not in feedback_info or 'status' not in feedback_info: + return {'error': 'Missing feedbackID or status'}, 400 + + status = feedback_info['status'] + feedback_id = feedback_info['feedbackID'] + + + query = ''' + UPDATE Feedback + SET status = %s + WHERE feedbackID = %s; + ''' + + + data = (status, feedback_id) + + cursor = db.get_db().cursor() + cursor.execute(query, data) + db.get_db().commit() + + return {'message': 'Feedback status updated successfully'}, 200 + + except KeyError as e: + current_app.logger.error(f"Missing key in request JSON: {str(e)}") + return {'error': f'Missing key: {str(e)}'}, 400 + except Exception as e: + current_app.logger.error(f"Error updating feedback: {str(e)}") + return {'error': 'An error occurred while updating feedback status'}, 500 + finally: + if 'cursor' in locals() and cursor: + cursor.close() + \ No newline at end of file From 9d39c65586c6a72e534313272cd2767a4744b38d Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 22:20:53 -0500 Subject: [PATCH 37/75] Fixed merge conflict --- app/src/pages/2001_Review_Form.py | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/app/src/pages/2001_Review_Form.py b/app/src/pages/2001_Review_Form.py index 81615954ce..b5c413fd0c 100644 --- a/app/src/pages/2001_Review_Form.py +++ b/app/src/pages/2001_Review_Form.py @@ -8,47 +8,17 @@ import numpy as np import plotly.express as px from modules.nav import SideBarLinks -<<<<<<< HEAD -======= import requests ->>>>>>> 1a7805cdae2c5c2a740b690b50489d4caf4191d4 # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() # set the header of the page -<<<<<<< HEAD -st.header('Find Company and Position Reviews') -======= st.header('Write A Co-Op Review') ->>>>>>> 1a7805cdae2c5c2a740b690b50489d4caf4191d4 # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -<<<<<<< HEAD -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) - -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) - - st.pyplot(test_plot) - - -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) -======= st.header("Submit a New Review") # Create a form @@ -83,4 +53,3 @@ st.success("Review submitted successfully!") except requests.exceptions.RequestException as e: st.error(f"An error occurred: {e}") ->>>>>>> 1a7805cdae2c5c2a740b690b50489d4caf4191d4 From 3f0d81e3b48302857a1f9dbcf2248d6feec66747 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 22:42:30 -0500 Subject: [PATCH 38/75] Company reviews page finished --- api/backend/coop_searcher/searcher_routes.py | 32 ++++++++++++++++++- .../pages/1001_Company_Position_Reviews.py | 13 +++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/api/backend/coop_searcher/searcher_routes.py b/api/backend/coop_searcher/searcher_routes.py index ff77d81560..a2db44b4ca 100644 --- a/api/backend/coop_searcher/searcher_routes.py +++ b/api/backend/coop_searcher/searcher_routes.py @@ -36,4 +36,34 @@ def get_companies_with_reviews(): response = make_response(jsonify(theData)) response.status_code = 200 - return response \ No newline at end of file + return response + +# Get reviews for a specific company +@searcher.route('/reviewsForCompany/', methods=['GET']) +def get_reviews_for_company(company_name): + + # Use parameterized query to prevent SQL injection + query = ''' + SELECT + rv.content + FROM + Reviews rv + JOIN + Role r ON rv.roleID = r.roleID + JOIN + Companies c ON r.companyID = c.companyID + WHERE + c.name = %s; + ''' + + # get the database connection, execute the query, and + # fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query, (company_name,)) # Passing company_name as a parameter + theData = cursor.fetchall() + + # Make the response + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index 2beef1ba30..ef240bd477 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -19,4 +19,15 @@ company_names = [item["CompanyName"] for item in results] # Display a dropdown menu with company names -selected_company = st.selectbox("Select a Company:", company_names) \ No newline at end of file +selected_company = st.selectbox("Select a Company:", company_names) + +# Fetch the reviews for the selected company by company name +reviews = requests.get(f'http://api:4000/s/reviewsForCompany/{selected_company}').json() + +# Display the reviews if available +if reviews: + st.write("### Reviews for this Company:") + # Display reviews in a table format + st.dataframe(reviews) +else: + st.write("No reviews available for this company.") \ No newline at end of file From c75fca9b26bff5dfde2a8633aba223ff751b3ce6 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 23:31:07 -0500 Subject: [PATCH 39/75] Skill matching page finished --- api/backend/coop_searcher/searcher_routes.py | 48 +++++++++++++++++++ app/src/pages/1002_Interview_Information.py | 28 ++++++++--- app/src/pages/1003_Skill_Matching.py | 50 ++++++++++++++++---- 3 files changed, 111 insertions(+), 15 deletions(-) diff --git a/api/backend/coop_searcher/searcher_routes.py b/api/backend/coop_searcher/searcher_routes.py index a2db44b4ca..e430cbfbd4 100644 --- a/api/backend/coop_searcher/searcher_routes.py +++ b/api/backend/coop_searcher/searcher_routes.py @@ -67,3 +67,51 @@ def get_reviews_for_company(company_name): response.status_code = 200 return response + +# Get possible skills +@searcher.route('/possibleSkills', methods=['GET']) +def get_possible_skills(): + # Query to get the skillsRequired for all roles + query = ''' + SELECT r.skillsRequired + FROM Role r; + ''' + + # Get the database connection, execute the query, and fetch the results + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +# Get roles that require a specific skill +@searcher.route('/rolesForSkill/', methods=['GET']) +def get_roles_for_skill(skill): + try: + # Query to find roles that require the specified skill + query = ''' + SELECT r.roleName, c.name AS companyName, r.skillsRequired + FROM Role r + JOIN Companies c ON r.companyID = c.companyID + WHERE r.skillsRequired LIKE %s; + ''' + + # Get the database connection, execute the query, and fetch the results + cursor = db.get_db().cursor() + cursor.execute(query, ('%' + skill + '%',)) # Using LIKE to match the skill within skillsRequired + theData = cursor.fetchall() + + # If no roles are found, log a warning + if not theData: + current_app.logger.warning(f"No roles found requiring the skill: {skill}") + + # Make the response + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + + except Exception as e: + # Log the error and return a 500 error response + current_app.logger.error(f"Error fetching roles for skill {skill}: {e}") + return make_response(jsonify({"error": "Database query failed"}), 500) diff --git a/app/src/pages/1002_Interview_Information.py b/app/src/pages/1002_Interview_Information.py index 906f4c915a..0a65fbfcfc 100644 --- a/app/src/pages/1002_Interview_Information.py +++ b/app/src/pages/1002_Interview_Information.py @@ -1,19 +1,33 @@ import logging logger = logging.getLogger(__name__) -import pandas as pd import streamlit as st -from streamlit_extras.app_logo import add_logo -import world_bank_data as wb -import matplotlib.pyplot as plt -import numpy as np -import plotly.express as px from modules.nav import SideBarLinks +import requests # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() # set the header of the page -st.header('View Interview Information and Tips') +st.header('Find Company and Position Reviews') # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") + +results = requests.get('http://api:4000/s/companiesWithReviews').json() + +# Extract company names into a list +company_names = [item["CompanyName"] for item in results] + +# Display a dropdown menu with company names +selected_company = st.selectbox("Select a Company:", company_names) + +# Fetch the reviews for the selected company by company name +reviews = requests.get(f'http://api:4000/s/reviewsForCompany/{selected_company}').json() + +# Display the reviews if available +if reviews: + st.write("### Interview Feedback for this Company:") + # Display reviews in a table format + st.dataframe(reviews) +else: + st.write("No reviews available for this company.") diff --git a/app/src/pages/1003_Skill_Matching.py b/app/src/pages/1003_Skill_Matching.py index 89e64ad220..a22517c7c9 100644 --- a/app/src/pages/1003_Skill_Matching.py +++ b/app/src/pages/1003_Skill_Matching.py @@ -1,20 +1,54 @@ import logging -logger = logging.getLogger(__name__) -import pandas as pd +import requests import streamlit as st -from streamlit_extras.app_logo import add_logo -import world_bank_data as wb -import matplotlib.pyplot as plt -import numpy as np -import plotly.express as px from modules.nav import SideBarLinks +import pandas as pd # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() -# set the header of the page +# Set the header of the page st.header('Find positions with matching skills') # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") +# Fetch the list of possible skills from the API +skills = requests.get('http://api:4000/s/possibleSkills').json() + + +# Extract and split skillsRequired into a list of individual skills +skillsRequired = [] +for item in skills: + # Split the skills by commas and strip any surrounding whitespace + skills = item["skillsRequired"].split(",") + # Add each skill to the list + skillsRequired.extend([skill.strip() for skill in skills]) + + +# Display a dropdown menu with company names +selected_skill = st.selectbox("Select a Skill:", skillsRequired) + +# If the user enters a skill +if selected_skill: + try: + # Send the GET request to the API endpoint with the skill + response = requests.get(f'http://api:4000/s/rolesForSkill/{selected_skill}') + + # Check if the response is successful (status code 200) + if response.status_code == 200: + data = response.json() + + # If there is data, display it in a table + if data: + # Convert the data into a Pandas DataFrame for easy display + df = pd.DataFrame(data, columns=['roleName', 'companyName', 'skillsRequired']) + st.write(f"### Roles that require the skill: {selected_skill}") + st.dataframe(df) # Display the DataFrame in Streamlit table format + else: + st.warning(f"No roles found that require the skill '{selected_skill}'.") + else: + st.error("Failed to fetch data from the server. Please try again later.") + + except requests.exceptions.RequestException as e: + st.error(f"Error fetching data: {e}") From 76f55280f54e0a2026a6d4487f365fea94361d57 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 23:32:57 -0500 Subject: [PATCH 40/75] can post reviews for specific company positions --- api/backend/reviews/reviews_routes.py | 107 ++++++++++++++++++++- app/src/pages/2001_Review_Form.py | 128 ++++++++++++++++++-------- app/src/pages/2002_My_Reviews.py | 15 +++ 3 files changed, 206 insertions(+), 44 deletions(-) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index be106866bd..991a4b92f7 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -10,16 +10,21 @@ from flask import current_app from backend.db_connection import db +from datetime import datetime + #------------------------------------------------------------ # Create a new Blueprint object, which is a collection of # routes. reviews = Blueprint('reviews', __name__) - @reviews.route('/addReview', methods=['POST']) def add_review(): review_data = request.json try: + # Get current timestamp for publishedAt + current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + # Construct SQL query to insert the review query = """ INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) @@ -27,19 +32,25 @@ def add_review(): values = ( review_data["userID"], review_data["roleID"], - review_data["publishedAt"], + current_time, # Use the current timestamp for publishedAt review_data["reviewType"], review_data["heading"], review_data["content"], - review_data["views"], - review_data["likes"], - review_data["isFlagged"] + 0, # Default views + 0, # Default likes + False # Default isFlagged ) + + # Execute the query cursor = db.get_db().cursor() cursor.execute(query, values) db.get_db().commit() + + # Return success response return jsonify({"message": "Review added successfully!"}), 201 + except Exception as e: + # Handle errors and return an error response error_message = str(e) print("Error:", error_message) print(traceback.format_exc()) @@ -83,6 +94,90 @@ def get_product_detail (id): response.status_code = 200 return response +@reviews.route('/roleDetails/', methods=['GET']) +def get_role_details(role_id): + query = f''' + SELECT + r.roleName, + c.companyName + FROM + Roles r + JOIN + Companies c ON r.companyID = c.companyID + WHERE + r.roleID = {str(role_id)}; + ''' + + # Get the database connection, execute the query, and fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query) + role_data = cursor.fetchone() # Assuming the result is a single row + + # If no result is found + if not role_data: + return jsonify({'error': 'Role not found'}), 404 + + response = { + 'roleName': role_data['roleName'], + 'companyName': role_data['companyName'] + } + + return make_response(jsonify(response), 200) + +@reviews.route('/companies', methods=['GET']) +def get_companies(): + query = ''' + SELECT + c.companyID, + c.name AS company_name, + c.description AS company_description, + c.createdAt AS company_createdAt, + c.updatedAt AS company_updatedAt + FROM + Companies c + ''' + # Execute the query + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +@reviews.route('/rolesByCompany/', methods=['GET']) +def get_roles_by_company(company_id): + query = f''' + SELECT + r.roleID, + r.roleName, + r.description AS role_description, + r.skillsRequired, + c.name AS company_name, + c.description AS company_description, + c.createdAt AS company_createdAt, + c.updatedAt AS company_updatedAt + FROM + Role r + JOIN + Companies c ON r.companyID = c.companyID + WHERE + r.companyID = {company_id}; + ''' + + # Get the database connection, execute the query, and fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query) + theData = cursor.fetchall() + + # Create the response + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + + + @reviews.route('/commentsByReview/', methods=['GET']) def get_comments_by_review(reviewID): query = f''' @@ -134,6 +229,8 @@ def update_review(): response.status_code = 200 return response + + #------------------------------------------------------------ # Get all the products from the database, package them up, # and return them to the client diff --git a/app/src/pages/2001_Review_Form.py b/app/src/pages/2001_Review_Form.py index b5c413fd0c..b2b540b8ac 100644 --- a/app/src/pages/2001_Review_Form.py +++ b/app/src/pages/2001_Review_Form.py @@ -1,55 +1,105 @@ import logging -logger = logging.getLogger(__name__) import pandas as pd import streamlit as st from streamlit_extras.app_logo import add_logo -import world_bank_data as wb -import matplotlib.pyplot as plt -import numpy as np +import requests import plotly.express as px from modules.nav import SideBarLinks -import requests + +# Initialize logger +logger = logging.getLogger(__name__) # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() -# set the header of the page -st.header('Write A Co-Op Review') +# Set the header of the page +st.header('My Reviews') -# You can access the session state to make a more customized/personalized app experience -st.write(f"### Hi, {st.session_state['first_name']}.") +# Display personalized greeting +st.write(f"### Hi, {st.session_state['first_name']}!") -st.header("Submit a New Review") +# Fetch the user's reviews +try: + response = requests.get(f'http://api:4000/r/reviewsByUser/{st.session_state["id"]}') + response.raise_for_status() + reviews = response.json() +except requests.exceptions.RequestException as e: + st.error(f"Failed to fetch reviews: {e}") + reviews = [] -# Create a form -with st.form("new_review_form"): - role_id = st.selectbox("Role", options=[1, 2, 3], format_func=lambda x: f"Role {x}") - review_type = st.selectbox("Review Type", options=["Experience", "Feedback", "Complaint"]) - heading = st.text_input("Heading", placeholder="Enter a brief heading for your review") - content = st.text_area("Content", placeholder="Write your review here...") - published_at = st.date_input("Published At") - - # Form submit button - submitted = st.form_submit_button("Submit") - -if submitted: - # Step 2: Prepare the data - new_review = { - "userID": st.session_state["id"], # Assuming the user's ID is stored in session_state - "roleID": role_id, - "publishedAt": published_at.isoformat(), # Convert to ISO format - "reviewType": review_type, - "heading": heading, - "content": content, - "views": 0, # Default value - "likes": 0, # Default value - "isFlagged": False # Default value - } - - # Step 3: Send the data to the API +# Function to fetch comments for a review +def fetch_comments(review_id): try: - response = requests.post("http://api:4000/r/addReview", json=new_review) + response = requests.get(f"http://api:4000/r/commentsByReview/{review_id}") response.raise_for_status() - st.success("Review submitted successfully!") + return response.json() except requests.exceptions.RequestException as e: - st.error(f"An error occurred: {e}") + logger.error(f"Failed to fetch comments for review {review_id}: {e}") + return [] + +# Fetch companies +try: + companies_response = requests.get("http://api:4000/r/companies") + companies_response.raise_for_status() + companies = companies_response.json() +except requests.exceptions.RequestException as e: + st.error(f"Error fetching companies: {e}") + companies = [] + +# Dropdown to select a company +if companies: + company_names = [company['company_name'] for company in companies] + selected_company_name = st.selectbox("Select a Company", company_names) + + # Fetch the selected company ID + selected_company = next(company for company in companies if company['company_name'] == selected_company_name) + selected_company_id = selected_company['companyID'] + + # Fetch roles for the selected company + try: + roles_response = requests.get(f"http://api:4000/r/rolesByCompany/{selected_company_id}") + roles_response.raise_for_status() + roles = roles_response.json() + except requests.exceptions.RequestException as e: + st.error(f"Error fetching roles: {e}") + roles = [] + + # Dropdown to select a role + if roles: + role_names = [role['roleName'] for role in roles] + selected_role_name = st.selectbox("Select a Role", role_names) + + # Fetch the selected role ID + selected_role = next(role for role in roles if role['roleName'] == selected_role_name) + selected_role_id = selected_role['roleID'] + + # Review submission form + with st.form("new_review_form"): + st.subheader("Submit a New Review") + + # Pre-fill the form with role info + st.write(f"Reviewing role: {selected_role_name} at {selected_company_name}") + + new_heading = st.text_input("Review Heading") + new_content = st.text_area("Content") + new_review_type = st.selectbox("Review Type", ["Experience", "Feedback", "Other"]) + + submit_button = st.form_submit_button("Submit Review") + + # Handle form submission + if submit_button: + review_data = { + "roleID": selected_role_id, + "heading": new_heading, + "content": new_content, + "reviewType": new_review_type, + "userID": st.session_state['id'] + } + + try: + submit_response = requests.post("http://api:4000/r/submitReview", json=review_data) + submit_response.raise_for_status() + st.success("Review submitted successfully!") + except requests.exceptions.RequestException as e: + st.error(f"Failed to submit review: {e}") + diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index dc423ce843..463b26a78f 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -27,6 +27,17 @@ st.error(f"Failed to fetch reviews: {e}") reviews = [] +# Function to fetch role and company details for each review +def fetch_role_and_company(role_id): + try: + response = requests.get(f"http://api:4000/r/roleDetails/{role_id}") + response.raise_for_status() + role_data = response.json() + return role_data.get('roleName', 'N/A'), role_data.get('companyName', 'N/A') + except requests.exceptions.RequestException as e: + logger.error(f"Failed to fetch role and company for role ID {role_id}: {e}") + return 'N/A', 'N/A' + # Function to fetch comments for a review def fetch_comments(review_id): try: @@ -42,10 +53,14 @@ def fetch_comments(review_id): st.subheader("Your Reviews") for review in reviews: with st.container(): + # Fetch role and company details + role_name, company_name = fetch_role_and_company(review['roleID']) + # Display review details st.markdown(f"### {review['heading']} ({review['reviewType']})") st.markdown(f"**Published At:** {review['publishedAt']}") st.markdown(f"**Views:** {review['views']} | **Likes:** {review['likes']}") + st.markdown(f"**Role:** {role_name} at **{company_name}**") st.markdown(f"**Content:** {review['content']}") # Fetch and display comments From 0924d0c5d30d24abafde4a653d448c7e264cdc7f Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 23:34:39 -0500 Subject: [PATCH 41/75] fix --- api/backend/reviews/reviews_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index 991a4b92f7..c2a202eba1 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -17,7 +17,7 @@ # routes. reviews = Blueprint('reviews', __name__) -@reviews.route('/addReview', methods=['POST']) +@reviews.route('/submitReview', methods=['POST']) def add_review(): review_data = request.json try: From fed561eff8dc15d5cd3ad677c44b2bdfc1d007bb Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 23:39:24 -0500 Subject: [PATCH 42/75] my reviews shows the role and company name! --- api/backend/reviews/reviews_routes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index c2a202eba1..a17630d990 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -99,9 +99,9 @@ def get_role_details(role_id): query = f''' SELECT r.roleName, - c.companyName + c.name FROM - Roles r + Role r JOIN Companies c ON r.companyID = c.companyID WHERE @@ -119,7 +119,7 @@ def get_role_details(role_id): response = { 'roleName': role_data['roleName'], - 'companyName': role_data['companyName'] + 'companyName': role_data['name'] } return make_response(jsonify(response), 200) From c67e8aca42ba0427de5565c861ef2e760c07f5f6 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 23:44:28 -0500 Subject: [PATCH 43/75] Interview Review works --- app/src/Home.py | 7 +- app/src/pages/1004_Enter_Interview_Info.py | 101 ++++++++++++++++++++- 2 files changed, 97 insertions(+), 11 deletions(-) diff --git a/app/src/Home.py b/app/src/Home.py index 6a57f04d70..61b08eb166 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -45,15 +45,10 @@ if st.button("Act as Sebastian, a Student Co-Op Searcher", type = 'primary', use_container_width=True): - # when user clicks the button, they are now considered authenticated st.session_state['authenticated'] = True - # we set the role of the current user st.session_state['role'] = 'Co-Op searcher' - # we add the first name of the user (so it can be displayed on - # subsequent pages). st.session_state['first_name'] = 'Sebastian' - # finally, we ask streamlit to switch to another page, in this case, the - # landing page for this particular user type + st.session_state['id'] = '5' logger.info("Logging in as Co-Op Searcher") st.switch_page('pages/100_CoOp_Searcher_Home.py') diff --git a/app/src/pages/1004_Enter_Interview_Info.py b/app/src/pages/1004_Enter_Interview_Info.py index c2c14eab75..e2af9d13b0 100644 --- a/app/src/pages/1004_Enter_Interview_Info.py +++ b/app/src/pages/1004_Enter_Interview_Info.py @@ -1,14 +1,105 @@ import logging -logger = logging.getLogger(__name__) +import pandas as pd import streamlit as st +from streamlit_extras.app_logo import add_logo +import requests +import plotly.express as px from modules.nav import SideBarLinks +# Initialize logger +logger = logging.getLogger(__name__) + # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() -# set the header of the page -st.header('Enter Information about your Interview experiences') +# Set the header of the page +st.header('My Reviews') + +# Display personalized greeting +st.write(f"### Hi, {st.session_state['first_name']}!") + +# Fetch the user's reviews +try: + response = requests.get(f'http://api:4000/r/reviewsByUser/{st.session_state["id"]}') + response.raise_for_status() + reviews = response.json() +except requests.exceptions.RequestException as e: + st.error(f"Failed to fetch reviews: {e}") + reviews = [] + +# Function to fetch comments for a review +def fetch_comments(review_id): + try: + response = requests.get(f"http://api:4000/r/commentsByReview/{review_id}") + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + logger.error(f"Failed to fetch comments for review {review_id}: {e}") + return [] + +# Fetch companies +try: + companies_response = requests.get("http://api:4000/r/companies") + companies_response.raise_for_status() + companies = companies_response.json() +except requests.exceptions.RequestException as e: + st.error(f"Error fetching companies: {e}") + companies = [] + +# Dropdown to select a company +if companies: + company_names = [company['company_name'] for company in companies] + selected_company_name = st.selectbox("Select a Company", company_names) + + # Fetch the selected company ID + selected_company = next(company for company in companies if company['company_name'] == selected_company_name) + selected_company_id = selected_company['companyID'] + + # Fetch roles for the selected company + try: + roles_response = requests.get(f"http://api:4000/r/rolesByCompany/{selected_company_id}") + roles_response.raise_for_status() + roles = roles_response.json() + except requests.exceptions.RequestException as e: + st.error(f"Error fetching roles: {e}") + roles = [] + + # Dropdown to select a role + if roles: + role_names = [role['roleName'] for role in roles] + selected_role_name = st.selectbox("Select a Role", role_names) + + # Fetch the selected role ID + selected_role = next(role for role in roles if role['roleName'] == selected_role_name) + selected_role_id = selected_role['roleID'] + + # Review submission form + with st.form("new_review_form"): + st.subheader("Submit an Interview Experience") + + # Pre-fill the form with role info + st.write(f"Reviewing interview for: {selected_role_name} at {selected_company_name}") + + new_heading = st.text_input("Review Heading") + new_content = st.text_area("Content") + new_review_type = "Interview Feedback" + + submit_button = st.form_submit_button("Submit Review") -# You can access the session state to make a more customized/personalized app experience -st.write(f"### Hi, {st.session_state['first_name']}.") + # Handle form submission + if submit_button: + review_data = { + "roleID": selected_role_id, + "heading": new_heading, + "content": new_content, + "reviewType": new_review_type, + "userID": st.session_state['id'] + } + try: + submit_response = requests.post("http://api:4000/r/submitReview", json=review_data) + submit_response.raise_for_status() + st.success("Review submitted successfully!") + except requests.exceptions.RequestException as e: + st.error(f"Failed to submit review: {e}") + From 73a4bc2b597b1cdcd9a3b22466cb897255b9287a Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Thu, 5 Dec 2024 23:49:30 -0500 Subject: [PATCH 44/75] added interview reports to the reviews dummy data --- app/src/pages/2002_My_Reviews.py | 4 +++- database-files/12_CoopPlatform_Data.sql | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index 463b26a78f..1f2c556eef 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -73,7 +73,9 @@ def fetch_comments(review_id): st.markdown("*No comments yet.*") # Display the edit button - if st.button(f"Edit Review", review['reviewID']): + edit_button = st.button(f"Edit Review {review['reviewID']}") + + if edit_button: # If the button is clicked, show the edit form with st.form(key=f'edit_review_{review["reviewID"]}'): st.subheader("Edit this Review") diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index 30c5a01ea8..190177c635 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -256,7 +256,12 @@ INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, (27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), (28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), (29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), -(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE); +(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE), +(31, 31, '2024-05-25 08:30:00', 'Interview Report', 'Interview Process at TechNova', 'The interview process was thorough with multiple technical rounds focusing on problem-solving and machine learning concepts. The final interview involved a coding challenge and a behavioral round.', 200, 45, FALSE), +(32, 32, '2024-05-28 09:00:00', 'Interview Report', 'Interview Process at GreenTech Solutions', 'Had a great experience during the interview process. It started with an initial screening, followed by two technical rounds. The interviewers were friendly, but the technical assessment was quite challenging.', 150, 30, FALSE), +(33, 33, '2024-06-01 10:15:00', 'Interview Report', 'Interview Process at SpaceX', 'The interview process was intense. First, a phone interview to discuss previous projects, then an onsite with coding exercises, and finally a behavioral interview to assess cultural fit. They were very focused on problem-solving skills.', 250, 55, FALSE), +(34, 34, '2024-06-05 13:00:00', 'Interview Report', 'Interview Process at Innovate Labs', 'The process included a 30-minute phone interview, followed by a technical test with algorithmic problems. I was impressed by the professionalism of the team and the quick turnaround time.', 180, 40, FALSE), +(35, 35, '2024-06-10 14:45:00', 'Interview Report', 'Interview Process at BioHealth Solutions', 'The interview process was well-structured. The first stage was a video interview with HR, followed by a second-stage technical interview where I was asked to solve coding problems related to healthcare technology.', 220, 50, FALSE); INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagged) VALUES From 91e4ad6131c30dd13c08b379a6d1e85f8eb2fa46 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Thu, 5 Dec 2024 23:49:36 -0500 Subject: [PATCH 45/75] Enter Interview report page updated --- app/src/pages/1004_Enter_Interview_Info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/pages/1004_Enter_Interview_Info.py b/app/src/pages/1004_Enter_Interview_Info.py index e2af9d13b0..815f1c008e 100644 --- a/app/src/pages/1004_Enter_Interview_Info.py +++ b/app/src/pages/1004_Enter_Interview_Info.py @@ -82,7 +82,7 @@ def fetch_comments(review_id): new_heading = st.text_input("Review Heading") new_content = st.text_area("Content") - new_review_type = "Interview Feedback" + new_review_type = "InterviewReport" submit_button = st.form_submit_button("Submit Review") From 7ee1eddaa730d5f1e4df40ab54058ead1ca02275 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Fri, 6 Dec 2024 00:53:10 -0500 Subject: [PATCH 46/75] add company for admin --- api/backend/companies/companies_routes.py | 77 +++++++++--- app/src/pages/3003_Company_Profiles.py | 140 +++++++++++++++------- 2 files changed, 154 insertions(+), 63 deletions(-) diff --git a/api/backend/companies/companies_routes.py b/api/backend/companies/companies_routes.py index 10ea780acc..b199bce40f 100644 --- a/api/backend/companies/companies_routes.py +++ b/api/backend/companies/companies_routes.py @@ -22,13 +22,13 @@ def get_feedback(): try: with db.get_db().cursor() as cursor: cursor.execute(''' - SELECT C.name, C.description, C.updatedAT, I.name, L.address, L.city, L.state_province, L.country, R.roleName, R.description, R.skillsRequired + SELECT C.companyID, C.name, C.description, C.updatedAT, I.name, L.address, L.city, L.state_province, L.country, R.roleName, R.description, R.skillsRequired, L.locationID AS `Location ID`, I.IndustryID AS `Industry ID`, R.roleID AS `Role ID` FROM Companies C JOIN Location L ON C.companyID = L.companyID JOIN CompanyIndustry CI ON CI.companyID = C.companyID JOIN Industries I ON I.industryID = CI.industryID JOIN Role R ON R.companyID = C.companyID - ORDER BY C.name ASC; + ORDER BY C.companyID, C.name ASC; ''') theData = cursor.fetchall() @@ -40,42 +40,81 @@ def get_feedback(): current_app.logger.error(f"Error fetching companies: {e}") return {"error": "An error occurred while fetching companies"}, 500 -''' -@feedback.route('/feedback', methods=['PUT']) -def update_status(): + +@companies.route('/companies/companies', methods=['PUT']) +def update_company(): current_app.logger.info('PUT /feedback route') try: - feedback_info = request.json + companies_info = request.json - if 'feedbackID' not in feedback_info or 'status' not in feedback_info: - return {'error': 'Missing feedbackID or status'}, 400 + if 'companyID' not in companies_info or 'Company Description' not in companies_info: + return {'error': 'Missing companyID or Company Description'}, 400 - status = feedback_info['status'] - feedback_id = feedback_info['feedbackID'] + company_id = companies_info['companyID'] + company_discription = companies_info['Company Description'] - query = - UPDATE Feedback - SET status = %s - WHERE feedbackID = %s; + query = ''' + UPDATE Companies + SET description = %s + WHERE companyID = %s + ''' + data = (company_discription, company_id) + + cursor = db.get_db().cursor() + cursor.execute(query, data) + db.get_db().commit() + + return {'message': 'Companies updated successfully'}, 200 + + except KeyError as e: + current_app.logger.error(f"Missing key in request JSON: {str(e)}") + return {'error': f'Missing key: {str(e)}'}, 400 + except Exception as e: + current_app.logger.error(f"Error updating feedback: {str(e)}") + return {'error': 'An error occurred while updating companies'}, 500 + finally: + if 'cursor' in locals() and cursor: + cursor.close() + + +@companies.route('/companies/roles', methods=['PUT']) +def update_roles(): + current_app.logger.info('PUT /feedback route') + try: + companies_info = request.json + + if 'RoleID' not in companies_info or 'Skills Required' not in companies_info or 'Role Description' not in companies_info: + return {'error': 'Missing RoleID or Skills Required or Role Description'}, 400 + + company_id = companies_info['companyID'] + role_id = companies_info['RoleID'] + skill = companies_info['Skills Required'] + role_description = companies_info['Role Description'] + query = ''' + UPDATE Role + SET description = %s, + skillsRequired = %s + WHERE companyID = %s AND roleID = %s; + ''' - data = (status, feedback_id) + data = (role_description, skill, company_id, role_id) cursor = db.get_db().cursor() cursor.execute(query, data) db.get_db().commit() - return {'message': 'Feedback status updated successfully'}, 200 + return {'message': 'Roles updated successfully'}, 200 except KeyError as e: current_app.logger.error(f"Missing key in request JSON: {str(e)}") return {'error': f'Missing key: {str(e)}'}, 400 except Exception as e: - current_app.logger.error(f"Error updating feedback: {str(e)}") - return {'error': 'An error occurred while updating feedback status'}, 500 + current_app.logger.error(f"Error updating roles: {str(e)}") + return {'error': 'An error occurred while updating roles'}, 500 finally: if 'cursor' in locals() and cursor: cursor.close() -''' + diff --git a/app/src/pages/3003_Company_Profiles.py b/app/src/pages/3003_Company_Profiles.py index 12b39fbe62..0e06871be4 100644 --- a/app/src/pages/3003_Company_Profiles.py +++ b/app/src/pages/3003_Company_Profiles.py @@ -49,10 +49,11 @@ time_threshold = dt.datetime.combine(time_threshold, dt.datetime.min.time()) - company_df = st.session_state.companies_df.copy() -company_df = company_df.rename(columns={'I.name': 'Industry', 'R.description':'Role Description', 'address':'Address', 'city':'City', 'country': 'Country', 'description':'Company Description', 'name': 'Company Name', 'roleName': 'Role Name', 'skillsRequired':'Skills Required', 'state_province':'State Province','updatedAT': 'Last Updated'}) -display_columns = ["Company Name", "Last Updated", "Industry", "Company Description", "Role Name", "Skills Required", "Role Description", "Address", "City", "State Province", "Country"] + + +company_df = company_df.rename(columns={'companyID':'Company ID','I.name': 'Industry', 'R.description':'Role Description', 'address':'Address', 'city':'City', 'country': 'Country', 'description':'Company Description', 'name': 'Company Name', 'roleName': 'Role Name', 'skillsRequired':'Skills Required', 'state_province':'State Province','updatedAT': 'Last Updated'}) +display_columns = ["Company ID", "Company Name", "Last Updated", "Industry", "Company Description", "Role Name", "Skills Required", "Role Description", "Address", "City", "State Province", "Country", 'Industry ID', 'Role ID','Location ID'] company_df = company_df[display_columns] company_df['Last Updated'] = pd.to_datetime(company_df['Last Updated']) @@ -68,11 +69,13 @@ if highlight_missing: def highlight_null_rows(df): def highlight_row(row): - if row.isnull().any(): + # Check for NaN or empty strings in the row + if row.isnull().any() or row.eq('').any(): return ['background-color: yellow'] * len(row) else: return [''] * len(row) - + + # Apply the highlighting function row-wise return df.style.apply(highlight_row, axis=1) styled_df = highlight_null_rows(company_df) @@ -80,44 +83,93 @@ def highlight_row(row): else: st.dataframe(company_df) -''' -# Update or edit company profiles -st.subheader("Edit or Update Company Profiles") -company_id = st.selectbox("Select Company ID to Edit", company_df["CompanyID"]) +st.subheader("Update Company Profiles") + +st.subheader("Delete Company Profiles") + +st.subheader("Edit Company Profiles") + + +company_id = st.selectbox("Select Company ID", sorted(company_df["Company ID"].unique())) +industry_id = st.selectbox("Select Industry ID", sorted(company_df["Industry ID"].unique())) +role_id = st.selectbox("Select Role ID", sorted(company_df["Role ID"].unique())) +location_id = st.selectbox("Select Location ID", sorted(company_df["Location ID"].unique())) + + + +if "flg" not in st.session_state: + st.session_state.flg = False +if "ssh" not in st.session_state: + st.session_state.ssh = False +if "company_df" not in st.session_state: + st.session_state.company_df = company_df + + +if st.button("Confirm") and not st.session_state.flg: + selected_company = company_df[company_df["Company ID"] == company_id] + filtered_company = selected_company[ + (selected_company["Industry ID"] == industry_id) & + (selected_company["Role ID"] == role_id) & + (selected_company["Location ID"] == location_id) + ] + if filtered_company.empty: + st.warning("No company meets your requirements. Please select again.") + else: + st.session_state.final_company = filtered_company + st.dataframe(filtered_company) + st.session_state.flg = True + + +if st.session_state.flg: + with st.form(key="edit_form"): + company_name = st.text_input("Company Name", st.session_state.final_company["Company Name"].iloc[0], disabled=True) + company_discription = st.text_input("Company Description", st.session_state.final_company["Company Description"].iloc[0]) + skill = st.text_input("Skills Required", st.session_state.final_company["Skills Required"].iloc[0]) + role_description = st.text_input("Role Description", st.session_state.final_company["Role Description"].iloc[0]) + + submitted = st.form_submit_button(label="Update Details") + if submitted: + condition = ( + (st.session_state.company_df["Company ID"] == company_id) & + (st.session_state.company_df["Industry ID"] == industry_id) & + (st.session_state.company_df["Role ID"] == role_id) & + (st.session_state.company_df["Location ID"] == location_id) + ) + + st.session_state.company_df.loc[(st.session_state.company_df["Company ID"] == company_id), "Company Description"] = company_discription + st.session_state.company_df.loc[(st.session_state.company_df["Company ID"] == company_id) & (st.session_state.company_df["Role ID"] == role_id), "Skills Required"] = skill + st.session_state.company_df.loc[(st.session_state.company_df["Company ID"] == company_id) & (st.session_state.company_df["Role ID"] == role_id), "Role Description"] = role_description + + + data = { + "companyID": company_id, + "RoleID": role_id, + "Company Description": company_discription, + "Skills Required": skill, + "Role Description": role_description + } + data = { + key: (int(value) if isinstance(value, np.int64) else value) + for key, value in data.items() + } + + response_company = requests.put("http://api:4000/c/companies/companies", json=data) + if response_company.status_code == 200: + print("Success:", response_company.json()) + else: + print("Error:", response_company.status_code, response_company.json()) + + response_role = requests.put("http://api:4000/c/companies/roles", json=data) + if response_role.status_code == 200: + print("Success:", response_role.json()) + else: + print("Error:", response_role.status_code, response_role.json()) + + st.session_state.ssh = True + -# Fetch selected company data -selected_company = company_df[company_df["CompanyID"] == company_id].iloc[0] -# Form for editing -with st.form(key="edit_form"): - company_name = st.text_input("Company Name", selected_company["CompanyName"]) - role = st.text_input("Role Description", selected_company["Role"]) - interview_details = st.text_area( - "Interview Details", selected_company["InterviewDetails"] - ) - submit_button = st.form_submit_button(label="Update Details") - - if submit_button: - st.session_state.company_data.loc[ - st.session_state.company_data["CompanyID"] == company_id, "CompanyName" - ] = company_name - st.session_state.company_data.loc[ - st.session_state.company_data["CompanyID"] == company_id, "Role" - ] = role - st.session_state.company_data.loc[ - st.session_state.company_data["CompanyID"] == company_id, "InterviewDetails" - ] = interview_details - st.session_state.company_data.loc[ - st.session_state.company_data["CompanyID"] == company_id, "LastUpdated" - ] = dt.datetime.now() - st.session_state.company_data.loc[ - st.session_state.company_data["CompanyID"] == company_id, "Status" - ] = "Complete" if role and interview_details else "Missing Data" - - st.success("Company details updated successfully!") - -# Display updated data -st.subheader("Updated Company Data") -updated_company_df = st.session_state.company_data.copy() -st.dataframe(updated_company_df) -''' +if st.session_state.ssh: + st.success("Company details updated successfully!") + st.subheader("Updated Company Data") + st.dataframe(st.session_state.company_df) \ No newline at end of file From 94ef1ecfeda4448a48f3fb158bde73a4a502095b Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Fri, 6 Dec 2024 00:59:51 -0500 Subject: [PATCH 47/75] update database --- database-files/12_CoopPlatform_Data.sql | 148 ++++++++++++------------ 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index 190177c635..9b0433c4cf 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -38,37 +38,38 @@ INSERT INTO User (firstName, lastName, email, major, skills, interests, isAdmin, ('Grace', 'Hopper', 'grace.hopper@example.com', 'Computer Science', 'Programming, Algorithms', 'Innovation, Women in Tech', TRUE, TRUE), ('Harvey', 'Specter', 'harvey.specter@example.com', 'Law', 'Litigation, Negotiation', 'Corporate Law, Strategy', FALSE, FALSE); -INSERT INTO Companies (name, description) VALUES -('TechNova Inc.', 'A leading company in AI and machine learning solutions.'), -('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.'), -('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.'), -('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.'), -('BrightFuture Education', 'Providing online and in-person educational programs worldwide.'), -('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.'), -('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.'), -('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.'), -('GlobalTech Solutions', 'Delivering IT consulting and software development services.'), -('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.'), -('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.'), -('FinPro Banking', 'A financial services firm offering innovative banking solutions.'), -('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.'), -('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.'), -('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.'), -('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.'), -('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.'), -('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.'), -('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.'), -('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.'), -('Visionary Designs', 'Offering innovative and stylish interior design services.'), -('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.'), -('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.'), -('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.'), -('DataPulse Analytics', 'Helping businesses harness big data for decision-making.'), -('GreenTech Farms', 'Implementing innovative vertical farming solutions.'), -('CloudNet Systems', 'Offering cloud computing and data storage services.'), -('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.'), -('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.'), -('QuantumLeap Solutions', 'Researching quantum computing and its applications.'); +INSERT INTO Companies (name, description, createdAt, updatedAt) VALUES +('TechNova Inc.', 'A leading company in AI and machine learning solutions.', '2020-05-14 12:34:56', '2022-11-01 15:45:30'), +('GreenFields Ltd.', 'Specializing in sustainable agriculture and organic farming techniques.', '2021-02-20 09:22:10', '2023-05-14 10:40:20'), +('SkyHigh Aerospace', 'An innovator in aerospace engineering and satellite technology.', '2020-09-10 14:18:20', '2023-01-27 19:34:50'), +('EcoEnergy Co.', NULL, '2020-06-01 11:45:10', '2021-12-19 16:22:10'), +#('EcoEnergy Co.', 'Focused on renewable energy solutions, including solar and wind power.', '2020-06-01 11:45:10', '2021-12-19 16:22:10'), +('BrightFuture Education', 'Providing online and in-person educational programs worldwide.', '2021-07-15 08:30:00', '2024-04-12 18:11:45'), +('HealthCore Pharmaceuticals', 'Researching and developing cutting-edge medications.', '2020-11-05 10:20:30', '2022-08-21 09:50:40'), +('UrbanBuilders LLC', 'An urban construction and architecture firm creating smart cities.', '2022-03-18 15:12:00', '2023-10-25 20:05:50'), +('AquaLife Systems', 'Revolutionizing water purification and desalination technologies.', '2021-09-12 13:25:30', '2024-01-10 14:40:30'), +('GlobalTech Solutions', 'Delivering IT consulting and software development services.', '2021-05-25 10:50:50', '2023-07-15 17:05:20'), +('Stellar Entertainment', 'Producing films, music, and streaming content for a global audience.', '2020-12-19 14:15:45', '2022-06-30 18:25:40'), +('NextGen Robotics', 'Designing robots for industrial, medical, and household applications.', '2020-04-10 11:10:10', '2024-03-05 10:55:00'), +('FinPro Banking', 'A financial services firm offering innovative banking solutions.', '2021-08-23 16:45:25', '2022-11-18 12:35:50'), +('AutoFuture Ltd.', 'Developing electric and autonomous vehicles.', '2020-01-05 09:30:15', '2023-09-29 15:45:25'), +('BioGenomics Inc.', 'Advancing genetic research and biotechnology applications.', '2022-02-11 18:00:00', '2023-06-12 11:22:33'), +('BlueOcean Logistics', 'A global logistics provider specializing in ocean freight.', '2021-03-17 14:50:35', '2024-02-01 12:00:45'), +('CyberShield Security', 'Protecting businesses with advanced cybersecurity solutions.', '2020-08-21 10:05:45', '2023-03-30 14:45:50'), +('Peak Performance Sports', 'Manufacturing high-quality sports equipment and apparel.', '2020-10-13 09:15:00', '2022-10-05 16:50:40'), +('EcoHomes Construction', 'Building eco-friendly and energy-efficient homes.', '2021-06-30 14:45:20', '2023-12-02 20:10:10'), +('VirtuMed Technologies', 'Developing virtual reality solutions for medical training.', '2020-03-25 13:40:10', '2022-09-21 15:45:45'), +('Gourmet World Foods', 'An international distributor of gourmet and specialty foods.', '2020-07-14 11:30:00', '2024-01-22 10:20:50'), +('Visionary Designs', 'Offering innovative and stylish interior design services.', '2021-01-10 12:15:25', '2023-05-01 09:40:30'), +('PetCare Innovations', 'Creating cutting-edge products for pet health and wellness.', '2021-04-07 14:22:30', '2023-10-15 13:45:50'), +('TravelSphere Ltd.', 'Providing unique travel experiences and adventure tours.', '2020-02-19 08:45:15', '2023-07-11 17:30:20'), +('FusionTech Manufacturing', 'Specializing in advanced manufacturing and automation.', '2020-11-11 12:50:45', '2024-05-20 19:50:40'), +('DataPulse Analytics', 'Helping businesses harness big data for decision-making.', '2022-01-18 10:25:00', '2023-08-30 14:55:30'), +('GreenTech Farms', 'Implementing innovative vertical farming solutions.', '2021-11-21 15:35:20', '2024-04-14 09:45:00'), +('CloudNet Systems', 'Offering cloud computing and data storage services.', '2021-10-09 17:15:45', '2023-09-03 11:05:10'), +('ArtisanCrafts Co.', 'Supporting local artisans through handcrafted product sales.', '2020-06-08 09:45:10', '2022-05-25 18:55:40'), +('BrightPath Logistics', 'Providing last-mile delivery solutions for e-commerce.', '2021-07-05 13:50:50', '2024-03-19 15:20:30'), +('QuantumLeap Solutions', 'Researching quantum computing and its applications.', '2020-09-15 14:10:45', '2023-06-25 12:45:50'); @@ -256,12 +257,7 @@ INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, (27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), (28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), (29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), -(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE), -(31, 31, '2024-05-25 08:30:00', 'Interview Report', 'Interview Process at TechNova', 'The interview process was thorough with multiple technical rounds focusing on problem-solving and machine learning concepts. The final interview involved a coding challenge and a behavioral round.', 200, 45, FALSE), -(32, 32, '2024-05-28 09:00:00', 'Interview Report', 'Interview Process at GreenTech Solutions', 'Had a great experience during the interview process. It started with an initial screening, followed by two technical rounds. The interviewers were friendly, but the technical assessment was quite challenging.', 150, 30, FALSE), -(33, 33, '2024-06-01 10:15:00', 'Interview Report', 'Interview Process at SpaceX', 'The interview process was intense. First, a phone interview to discuss previous projects, then an onsite with coding exercises, and finally a behavioral interview to assess cultural fit. They were very focused on problem-solving skills.', 250, 55, FALSE), -(34, 34, '2024-06-05 13:00:00', 'Interview Report', 'Interview Process at Innovate Labs', 'The process included a 30-minute phone interview, followed by a technical test with algorithmic problems. I was impressed by the professionalism of the team and the quick turnaround time.', 180, 40, FALSE), -(35, 35, '2024-06-10 14:45:00', 'Interview Report', 'Interview Process at BioHealth Solutions', 'The interview process was well-structured. The first stage was a video interview with HR, followed by a second-stage technical interview where I was asked to solve coding problems related to healthcare technology.', 220, 50, FALSE); +(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE); INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagged) VALUES @@ -349,40 +345,44 @@ INSERT INTO UserBadges (userID, badgeID) VALUES -INSERT INTO Feedback (userID, header, content) VALUES -(1, 'Platform Improvement Suggestion', 'It would be great to have a dark mode feature for the platform.'), -(2, 'Bug Report', 'I encountered an error when trying to submit my review.'), -(3, 'Feature Request', 'A section for trending roles and reviews would be very useful.'), -(4, 'Positive Experience', 'The platform is user-friendly and intuitive. Keep up the great work!'), -(5, 'Role Matching Feedback', 'Role recommendations based on my skills are very accurate.'), -(6, 'Data Visualization Suggestion', 'Adding charts for role trends and analytics would be helpful.'), -(7, 'User Profile Customization', 'I’d like more options to customize my profile page.'), -(8, 'Slow Loading Issue', 'The reviews page sometimes loads very slowly.'), -(9, 'Mobile App Suggestion', 'A dedicated mobile app would improve accessibility.'), -(10, 'Content Moderation Concern', 'Some comments seem inappropriate and should be flagged faster.'), -(11, 'Review Sorting', 'Adding filters for reviews by date or popularity would be helpful.'), -(12, 'Badge System Feedback', 'The badge system is great but could be expanded with more levels.'), -(13, 'Search Functionality', 'The search bar could use better predictive text features.'), -(14, 'Community Engagement', 'The platform could host live events to foster more engagement.'), -(15, 'Navigation Improvement', 'The navigation menu could be more streamlined for new users.'), -(16, 'Privacy Concerns', 'I’d like more clarity on how my data is being used.'), -(17, 'Content Quality', 'Some reviews lack depth and could benefit from a word minimum.'), -(18, 'Notification Settings', 'Customizing notifications would make the experience better.'), -(19, 'Integration Request', 'Integration with LinkedIn would be highly beneficial.'), -(20, 'Overall Feedback', 'This platform has a lot of potential and is already very useful.'), -(21, 'Search Filter Request', 'Filters for location-based role searches would be very helpful.'), -(22, 'Comment Editing Option', 'It would be great if users could edit their comments after posting.'), -(23, 'Collaboration Features', 'Adding group discussions for roles or industries would foster collaboration.'), -(24, 'Enhanced Analytics', 'Role analytics could include average salaries and career growth trends.'), -(25, 'Email Notification Issues', 'I am not receiving email notifications for new comments on my reviews.'), -(26, 'Review Draft Saving', 'The ability to save a review as a draft would be helpful.'), -(27, 'Expanded Industry List', 'The platform could include more industries to choose from.'), -(28, 'User Verification', 'Adding user verification would increase trust in the community.'), -(29, 'Role Comparison Tool', 'A feature to compare roles side-by-side would be useful.'), -(30, 'Feedback Acknowledgement', 'It would be nice to get updates on submitted feedback.'), -(1, 'Improved Role Details', 'Providing detailed role descriptions with responsibilities would be helpful.'), -(2, 'Live Chat Support', 'Adding a live chat feature for user support would be beneficial.'), -(3, 'More Badge Categories', 'The badge system could include categories for mentorship and learning.'), -(4, 'Mentorship Program', 'A mentorship program linking experienced users with newcomers would be valuable.'), -(5, 'Content Curation', 'Curating high-quality reviews or featuring top contributors could inspire others.'); - +INSERT INTO Feedback (userID, header, content, status) VALUES +(1, 'Great Service', 'I really appreciate the recent updates to the app.', 'In Progress'), +(2, 'Feature Request', 'Could you add a scheduling feature for tasks?', 'Implemented'), +(3, 'Bug Report', 'The app freezes when trying to generate a report.', 'In Progress'), +(4, 'Login Issue', 'Unable to reset my password using the forgot password option.', 'Rejected'), +(5, 'UI Feedback', 'The new layout is great, but the text is too small.', 'Implemented'), +(6, 'Performance Issue', 'The site becomes unresponsive during peak hours.', 'In Progress'), +(7, 'Dark Mode', 'Dark mode would improve usability at night.', 'Implemented'), +(8, 'Security Concern', 'Is there two-factor authentication available?', 'Rejected'), +(9, 'Account Feature', 'Can you provide an option to link multiple accounts?', 'In Progress'), +(10, 'Pricing Feedback', 'The pricing tiers seem unclear to new users.', 'Rejected'), +(11, 'New Feature', 'Adding analytics dashboards would be a great feature.', 'Implemented'), +(12, 'Mobile App Issue', 'The mobile app crashes when scrolling through large lists.', 'In Progress'), +(13, 'Positive Feedback', 'The team is doing a fantastic job with updates.', 'Implemented'), +(14, 'Bug in Search', 'The search function does not return relevant results.', 'In Progress'), +(15, 'User Permissions', 'Please allow admins to set custom permissions.', 'Implemented'), +(16, 'Customer Support', 'Your customer support resolved my issue quickly!', 'Rejected'), +(17, 'Feature Request', 'It would be great to have offline mode in the app.', 'Implemented'), +(18, 'Slow Loading', 'Pages take a long time to load on mobile devices.', 'In Progress'), +(19, 'API Enhancement', 'Can you add more filters to the API endpoints?', 'Rejected'), +(20, 'Email Notifications', 'The email notifications are inconsistent.', 'In Progress'), +(21, 'Dashboard Update', 'I like the new dashboard, but it feels a bit cluttered.', 'Implemented'), +(22, 'Integration Request', 'Can you integrate with XYZ service?', 'Rejected'), +(23, 'Navigation Issue', 'The navigation menu disappears on smaller screens.', 'In Progress'), +(24, 'Search Enhancement', 'Can you add autocomplete to the search bar?', 'Implemented'), +(25, 'Feature Idea', 'How about a collaborative editing feature?', 'In Progress'), +(26, 'UI Feedback', 'The color contrast is not accessible for all users.', 'Rejected'), +(27, 'Report Generation', 'Reports take too long to generate.', 'Implemented'), +(28, 'Settings Option', 'Allow users to export their settings as a file.', 'In Progress'), +(29, 'Appreciation', 'The recent updates have been excellent!', 'Implemented'), +(30, 'Feedback on Beta', 'The beta version is unstable on older devices.', 'Rejected'), +(1, 'Suggestion', 'Add a save as draft option for posts.', 'Implemented'), +(2, 'Account Settings', 'The account settings are difficult to navigate.', 'In Progress'), +(3, 'Feature Request', 'Include a timer for sessions.', 'Rejected'), +(4, 'UI Improvement', 'The text alignment on the settings page is off.', 'In Progress'), +(5, 'Server Downtime', 'The server goes down frequently in my region.', 'Implemented'), +(6, 'Password Management', 'Add a password strength indicator.', 'Rejected'), +(7, 'Onboarding', 'The onboarding process is not very user-friendly.', 'In Progress'), +(8, 'Localization', 'Can you add support for more languages?', 'Implemented'), +(9, 'Social Media', 'Integrate with popular social media platforms.', 'Rejected'), +(10, 'Billing System', 'The billing system has recurring issues.', 'In Progress'); From 5efb094db0aef4f3a9fa47cffda7a3ebf9a7690a Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Fri, 6 Dec 2024 01:02:34 -0500 Subject: [PATCH 48/75] Update 3004_User_Feedback.py --- app/src/pages/3004_User_Feedback.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index e4c114f838..6afea7c6df 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -18,15 +18,6 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -<<<<<<< HEAD -# get the feedbacks -try: - feedback = requests.get("http://api:4000/f/feedback").json() - st.dataframe(feedback) -except: - st.write("Could not to conncet to database to get user feedback") -======= - # get the feedbacks try: feedback = requests.get("http://api:4000/f/feedback").json() From 1144fd77ce9a6a18e3fb71d675e57499e64df0d2 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Fri, 6 Dec 2024 01:29:15 -0500 Subject: [PATCH 49/75] update database --- api/.env | 2 +- app/src/pages/3002_Flagged_Posts.py | 85 +++++++++++++++++++------ app/src/pages/3004_User_Feedback.py | 11 +--- database-files/12_CoopPlatform_Data.sql | 10 +-- 4 files changed, 71 insertions(+), 37 deletions(-) diff --git a/api/.env b/api/.env index fcb5a4bddb..14b676e4f4 100644 --- a/api/.env +++ b/api/.env @@ -3,4 +3,4 @@ DB_USER=root DB_HOST=db DB_PORT=3306 DB_NAME=CoopPlatform -MYSQL_ROOT_PASSWORD=password +MYSQL_ROOT_PASSWORD=CoopPCrazyS3 diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py index aa3d3b224d..6b9aaa3d1b 100644 --- a/app/src/pages/3002_Flagged_Posts.py +++ b/app/src/pages/3002_Flagged_Posts.py @@ -18,24 +18,67 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) - -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) - - st.pyplot(test_plot) - - -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) \ No newline at end of file +import streamlit as st +import pandas as pd +from datetime import datetime + +# Sample data for flagged posts +sample_data = [ + {"Post ID": 1, "Content": "This is a flagged post.", "Flag Reason": "Inappropriate Language", "History": []}, + {"Post ID": 2, "Content": "Another flagged post here.", "Flag Reason": "Spam", "History": []}, +] + +# Convert sample data to DataFrame +posts_df = pd.DataFrame(sample_data) + +# Function to log actions +def log_action(post_id, action, reason=None): + for post in sample_data: + if post["Post ID"] == post_id: + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + post["History"].append({"Action": action, "Reason": reason, "Timestamp": timestamp}) + +# Streamlit app +st.title("Flagged Posts Review Interface") + +# Display flagged posts +st.subheader("Flagged Posts") + +for index, row in posts_df.iterrows(): + st.write(f"**Post ID:** {row['Post ID']}") + st.write(f"**Content:** {row['Content']}") + st.write(f"**Flag Reason:** {row['Flag Reason']}") + + # Buttons for actions + col1, col2, col3 = st.columns(3) + + with col1: + if st.button(f"Approve Post {row['Post ID']}"): + log_action(row['Post ID'], "Approved") + st.success(f"Post {row['Post ID']} approved.") + + with col2: + if st.button(f"Edit Post {row['Post ID']}"): + new_content = st.text_area(f"Edit Content for Post {row['Post ID']}", row['Content']) + if st.button(f"Save Changes to Post {row['Post ID']}"): + posts_df.loc[index, "Content"] = new_content + log_action(row['Post ID'], "Edited", f"Updated content to: {new_content}") + st.success(f"Post {row['Post ID']} updated.") + + with col3: + if st.button(f"Remove Post {row['Post ID']}"): + log_action(row['Post ID'], "Removed") + st.warning(f"Post {row['Post ID']} removed.") + + # Display action history + st.write("**Action History:**") + history = row['History'] + if history: + for entry in history: + st.write(f"- {entry['Timestamp']} - {entry['Action']} ({entry.get('Reason', 'No Reason')})") + else: + st.write("No actions taken yet.") + + st.divider() + +st.write("**Note:** This interface uses sample data. Replace with actual data for production.") diff --git a/app/src/pages/3004_User_Feedback.py b/app/src/pages/3004_User_Feedback.py index e4c114f838..ff653ff548 100644 --- a/app/src/pages/3004_User_Feedback.py +++ b/app/src/pages/3004_User_Feedback.py @@ -18,15 +18,6 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -<<<<<<< HEAD -# get the feedbacks -try: - feedback = requests.get("http://api:4000/f/feedback").json() - st.dataframe(feedback) -except: - st.write("Could not to conncet to database to get user feedback") -======= - # get the feedbacks try: feedback = requests.get("http://api:4000/f/feedback").json() @@ -130,4 +121,4 @@ st.dataframe(filtered_feedback_df) ->>>>>>> 1a7805cdae2c5c2a740b690b50489d4caf4191d4 + diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index 9b0433c4cf..de5fc087c7 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -230,14 +230,14 @@ INSERT INTO Role (companyID, locationID, roleName, description, skillsRequired) INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES (1, 1, '2024-01-01 10:00:00', 'Experience', 'Great Experience as an ML Engineer', 'I had a fantastic experience working as a Machine Learning Engineer at TechNova Inc. Learned a lot about AI.', 150, 35, FALSE), (2, 2, '2024-01-05 15:30:00', 'Feedback', 'Improved Sustainability Practices', 'The company is making significant strides in sustainability, but communication needs improvement.', 100, 20, FALSE), -(3, 3, '2024-01-10 09:45:00', 'Review', 'Exciting Role in Aerospace', 'Working on cutting-edge technology was inspiring. Would recommend it to any aspiring engineer.', 200, 50, FALSE), +(3, 3, '2024-01-10 09:45:00', 'Review', 'Exciting Role in Aerospace', 'Working on cutting-edge technology was inspiring. Would recommend it to any aspiring engineer.', 200, 50, TRUE), (4, 4, '2024-01-15 14:20:00', 'Insight', 'Great Opportunity in Renewable Energy', 'A rewarding experience with excellent leadership and vision.', 120, 25, FALSE), -(5, 5, '2024-01-20 11:10:00', 'Experience', 'Rewarding Work Environment', 'Collaborative culture and strong focus on education made my role enjoyable.', 90, 15, FALSE), +(5, 5, '2024-01-20 11:10:00', 'Experience', 'Rewarding Work Environment', 'Collaborative culture and strong focus on education made my role enjoyable.', 90, 15, TRUE), (6, 6, '2024-01-25 17:00:00', 'Feedback', 'Cutting-Edge Research', 'Involved in exciting research but workload was quite heavy.', 140, 30, FALSE), (7, 7, '2024-02-01 08:00:00', 'Review', 'Urban Development at Its Best', 'Loved working on innovative projects for smart cities.', 85, 10, FALSE), (8, 8, '2024-02-05 10:30:00', 'Insight', 'Advancing Water Purification', 'Meaningful work but limited opportunities for growth.', 70, 12, FALSE), (9, 9, '2024-02-10 13:15:00', 'Experience', 'Dynamic Work Environment', 'Fast-paced and challenging, great place for software enthusiasts.', 180, 40, FALSE), -(10, 10, '2024-02-15 16:45:00', 'Feedback', 'Creative and Supportive', 'Perfect workplace for creative professionals.', 75, 18, FALSE), +(10, 10, '2024-02-15 16:45:00', 'Feedback', 'Creative and Supportive', 'Perfect workplace for creative professionals.', 75, 18, TRUE), (11, 11, '2024-02-20 19:20:00', 'Review', 'Robotics Projects Worth Pursuing', 'Exciting projects but management needs improvement.', 95, 20, FALSE), (12, 12, '2024-02-25 07:30:00', 'Insight', 'Great Start for Financial Analysts', 'Supportive team and ample learning opportunities.', 105, 22, FALSE), (13, 13, '2024-03-01 11:50:00', 'Experience', 'Innovative Role in Automotive', 'Hands-on experience with cutting-edge technologies.', 130, 35, FALSE), @@ -246,14 +246,14 @@ INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, (16, 16, '2024-03-15 14:00:00', 'Insight', 'Top-notch Cybersecurity Expertise', 'Fantastic workplace for security professionals.', 200, 50, FALSE), (17, 17, '2024-03-20 15:30:00', 'Experience', 'Challenging Sports Equipment Design', 'Opportunity to innovate, but tight deadlines.', 60, 10, FALSE), (18, 18, '2024-03-25 16:45:00', 'Feedback', 'Sustainable and Collaborative', 'Loved the eco-friendly approach and teamwork.', 95, 25, FALSE), -(19, 19, '2024-03-30 10:10:00', 'Review', 'Immersive VR Development', 'Great exposure to VR development, but lacked mentorship.', 120, 18, FALSE), +(19, 19, '2024-03-30 10:10:00', 'Review', 'Immersive VR Development', 'Great exposure to VR development, but lacked mentorship.', 120, 18, TRUE), (20, 20, '2024-04-01 13:00:00', 'Insight', 'Delicious Career Growth', 'Enjoyed working on gourmet food projects.', 80, 16, FALSE), (21, 21, '2024-04-05 14:30:00', 'Experience', 'Creative Interior Design Projects', 'Amazing projects but needs better client communication.', 110, 20, FALSE), (22, 22, '2024-04-10 09:15:00', 'Feedback', 'Innovative Pet Products', 'Great workplace with a fun and collaborative culture.', 90, 22, FALSE), (23, 23, '2024-04-15 10:45:00', 'Review', 'Rewarding Travel Role', 'TravelSphere provides ample learning opportunities.', 115, 18, FALSE), (24, 24, '2024-04-20 11:30:00', 'Insight', 'Streamlined Manufacturing Process', 'High-tech projects but long hours.', 130, 24, FALSE), (25, 25, '2024-04-25 16:00:00', 'Experience', 'Data-Driven Insights', 'DataPulse offers cutting-edge analytics projects.', 170, 40, FALSE), -(26, 26, '2024-05-01 09:40:00', 'Feedback', 'Smart Agricultural Practices', 'Good place to grow for agricultural engineers.', 140, 35, FALSE), +(26, 26, '2024-05-01 09:40:00', 'Feedback', 'Smart Agricultural Practices', 'Good place to grow for agricultural engineers.', 140, 35, TRUE), (27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), (28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), (29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), From b3ba705463f939103b65b25a809f8c95a6e95e12 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Fri, 6 Dec 2024 01:47:36 -0500 Subject: [PATCH 50/75] Writing and viewing interview reports is now possible with dummy data and routes --- api/backend/coop_searcher/searcher_routes.py | 53 ++++++++++++++++---- app/src/pages/1002_Interview_Information.py | 4 +- app/src/pages/2001_Review_Form.py | 2 +- database-files/12_CoopPlatform_Data.sql | 39 +++++++++++--- 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/api/backend/coop_searcher/searcher_routes.py b/api/backend/coop_searcher/searcher_routes.py index e430cbfbd4..e6ec9ce491 100644 --- a/api/backend/coop_searcher/searcher_routes.py +++ b/api/backend/coop_searcher/searcher_routes.py @@ -44,16 +44,49 @@ def get_reviews_for_company(company_name): # Use parameterized query to prevent SQL injection query = ''' - SELECT - rv.content - FROM - Reviews rv - JOIN - Role r ON rv.roleID = r.roleID - JOIN - Companies c ON r.companyID = c.companyID - WHERE - c.name = %s; + SELECT + rv.content + FROM + Reviews rv + JOIN + Role r ON rv.roleID = r.roleID + JOIN + Companies c ON r.companyID = c.companyID + WHERE + c.name = %s + + ''' + + # get the database connection, execute the query, and + # fetch the results as a Python Dictionary + cursor = db.get_db().cursor() + cursor.execute(query, (company_name,)) # Passing company_name as a parameter + theData = cursor.fetchall() + + # Make the response + response = make_response(jsonify(theData)) + response.status_code = 200 + return response + +# Get reviews for a specific company +@searcher.route('/interviewReportsForCompany/', methods=['GET']) +def get_interview_reports_for_company(company_name): + + # Use parameterized query to prevent SQL injection + query = ''' + SELECT + rv.content + FROM + Reviews rv + JOIN + Role r ON rv.roleID = r.roleID + JOIN + Companies c ON r.companyID = c.companyID + WHERE + c.name = %s + AND + rv.reviewType = 'InterviewReport' + ''' # get the database connection, execute the query, and diff --git a/app/src/pages/1002_Interview_Information.py b/app/src/pages/1002_Interview_Information.py index 0a65fbfcfc..0fce324637 100644 --- a/app/src/pages/1002_Interview_Information.py +++ b/app/src/pages/1002_Interview_Information.py @@ -22,7 +22,7 @@ selected_company = st.selectbox("Select a Company:", company_names) # Fetch the reviews for the selected company by company name -reviews = requests.get(f'http://api:4000/s/reviewsForCompany/{selected_company}').json() +reviews = requests.get(f'http://api:4000/s/interviewReportsForCompany/{selected_company}').json() # Display the reviews if available if reviews: @@ -30,4 +30,4 @@ # Display reviews in a table format st.dataframe(reviews) else: - st.write("No reviews available for this company.") + st.write("No interview feedback available for this company.") diff --git a/app/src/pages/2001_Review_Form.py b/app/src/pages/2001_Review_Form.py index b2b540b8ac..62b63b7665 100644 --- a/app/src/pages/2001_Review_Form.py +++ b/app/src/pages/2001_Review_Form.py @@ -82,7 +82,7 @@ def fetch_comments(review_id): new_heading = st.text_input("Review Heading") new_content = st.text_area("Content") - new_review_type = st.selectbox("Review Type", ["Experience", "Feedback", "Other"]) + new_review_type = st.selectbox("Review Type", ["Experience", "InterviewReport", "Feedback", "Other"]) submit_button = st.form_submit_button("Submit Review") diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index 190177c635..94f53c8429 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -227,7 +227,7 @@ INSERT INTO Role (companyID, locationID, roleName, description, skillsRequired) (30, 30, 'Quantum Computing Researcher', 'Research and develop quantum computing applications.', 'Quantum Mechanics, Algorithms'); INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES -(1, 1, '2024-01-01 10:00:00', 'Experience', 'Great Experience as an ML Engineer', 'I had a fantastic experience working as a Machine Learning Engineer at TechNova Inc. Learned a lot about AI.', 150, 35, FALSE), +(1, 1, '2024-01-01 10:00:00', 'InterviewReport', 'Tricky questions about Python', 'It was so hard to figure out their python related questions.', 150, 35, FALSE), (2, 2, '2024-01-05 15:30:00', 'Feedback', 'Improved Sustainability Practices', 'The company is making significant strides in sustainability, but communication needs improvement.', 100, 20, FALSE), (3, 3, '2024-01-10 09:45:00', 'Review', 'Exciting Role in Aerospace', 'Working on cutting-edge technology was inspiring. Would recommend it to any aspiring engineer.', 200, 50, FALSE), (4, 4, '2024-01-15 14:20:00', 'Insight', 'Great Opportunity in Renewable Energy', 'A rewarding experience with excellent leadership and vision.', 120, 25, FALSE), @@ -256,13 +256,38 @@ INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, (27, 27, '2024-05-05 11:30:00', 'Review', 'Innovative Cloud Technologies', 'Great workplace for cloud engineers.', 125, 30, FALSE), (28, 28, '2024-05-10 14:15:00', 'Insight', 'Artisan Product Design', 'Creative work with room for growth.', 95, 12, FALSE), (29, 29, '2024-05-15 10:00:00', 'Experience', 'Efficient E-commerce Operations', 'Fast-paced environment with rewarding challenges.', 80, 18, FALSE), -(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE), -(31, 31, '2024-05-25 08:30:00', 'Interview Report', 'Interview Process at TechNova', 'The interview process was thorough with multiple technical rounds focusing on problem-solving and machine learning concepts. The final interview involved a coding challenge and a behavioral round.', 200, 45, FALSE), -(32, 32, '2024-05-28 09:00:00', 'Interview Report', 'Interview Process at GreenTech Solutions', 'Had a great experience during the interview process. It started with an initial screening, followed by two technical rounds. The interviewers were friendly, but the technical assessment was quite challenging.', 150, 30, FALSE), -(33, 33, '2024-06-01 10:15:00', 'Interview Report', 'Interview Process at SpaceX', 'The interview process was intense. First, a phone interview to discuss previous projects, then an onsite with coding exercises, and finally a behavioral interview to assess cultural fit. They were very focused on problem-solving skills.', 250, 55, FALSE), -(34, 34, '2024-06-05 13:00:00', 'Interview Report', 'Interview Process at Innovate Labs', 'The process included a 30-minute phone interview, followed by a technical test with algorithmic problems. I was impressed by the professionalism of the team and the quick turnaround time.', 180, 40, FALSE), -(35, 35, '2024-06-10 14:45:00', 'Interview Report', 'Interview Process at BioHealth Solutions', 'The interview process was well-structured. The first stage was a video interview with HR, followed by a second-stage technical interview where I was asked to solve coding problems related to healthcare technology.', 220, 50, FALSE); +(30, 30, '2024-05-20 15:00:00', 'Feedback', 'Quantum Computing Innovations', 'Fascinating projects but steep learning curve.', 145, 28, FALSE); +INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES +(2, 1, '2024-01-05 15:30:00', 'InterviewReport', 'Machine Learning Frameworks', 'They grilled me on machine learning frameworks like TensorFlow and PyTorch. Be ready for some deep technical discussions.', 130, 40, FALSE), +(3, 2, '2024-01-10 09:45:00', 'InterviewReport', 'Sustainability Practices in Agriculture', 'Expect detailed questions on sustainable farming techniques. They tested my knowledge of real-world agricultural challenges.', 180, 50, FALSE), +(4, 2, '2024-01-15 14:20:00', 'InterviewReport', 'Sustainability Metrics', 'They focused on sustainability metrics and how I would apply them to optimize farming practices.', 120, 30, FALSE), +(5, 3, '2024-01-20 11:10:00', 'InterviewReport', 'Aerospace Engineering Concepts', 'Be prepared for questions on spacecraft propulsion and satellite design. Technical, but stimulating!', 160, 45, FALSE), +(6, 3, '2024-01-25 17:00:00', 'InterviewReport', 'Advanced Aerospace Technology', 'They asked about advanced aerospace technologies and how I would improve existing designs.', 150, 40, FALSE), +(7, 4, '2024-02-01 08:00:00', 'InterviewReport', 'Renewable Energy Challenges', 'They asked about the challenges in renewable energy, especially regarding solar technology. Make sure to know your data.', 140, 38, FALSE), +(8, 4, '2024-02-05 10:30:00', 'InterviewReport', 'Solar Energy Design', 'The interview focused on solar energy design and real-life applications of green energy.', 110, 28, FALSE), +(9, 5, '2024-02-10 13:15:00', 'InterviewReport', 'Curriculum Design in Education', 'They asked how to design curricula for diverse learners, focusing on interactive learning strategies.', 180, 50, FALSE), +(10, 6, '2024-02-15 16:45:00', 'InterviewReport', 'Educational Content Challenges', 'Expect questions about educational content development under time constraints and adapting materials to different learning styles.', 140, 35, FALSE), +(11, 7, '2024-02-20 19:20:00', 'InterviewReport', 'Clinical Trials and Data Analysis', 'The focus was on clinical trial design, including statistical methods and data analysis challenges.', 200, 55, FALSE), +(12, 6, '2024-02-25 07:30:00', 'InterviewReport', 'Pharmaceutical Research Experience', 'Expect to discuss your past experience in pharmaceutical research, including data-driven decision making.', 170, 45, FALSE), +(13, 7, '2024-03-01 11:50:00', 'InterviewReport', 'Urban Development Strategies', 'They asked about sustainable urban development strategies and smart city concepts.', 150, 38, FALSE), +(14, 8, '2024-03-05 09:40:00', 'InterviewReport', 'Smart City Design', 'Expect to discuss your approach to designing smart city infrastructures, focusing on technological integration.', 140, 35, FALSE), +(15, 9, '2024-03-10 12:25:00', 'InterviewReport', 'Water Purification Systems', 'They asked about advanced water purification technologies and challenges in real-world applications.', 130, 33, FALSE), +(16, 10, '2024-03-15 14:00:00', 'InterviewReport', 'Water Systems Engineering Problems', 'The interview involved real-life engineering problems related to water desalination and purification.', 120, 30, FALSE), +(17, 11, '2024-03-20 15:30:00', 'InterviewReport', 'Software Development Process', 'The interview focused on software development methodologies and tools, including problem-solving during live coding challenges.', 200, 55, FALSE), +(18, 12, '2024-03-25 16:45:00', 'InterviewReport', 'Coding Challenges in Software Engineering', 'Expect live coding challenges focusing on algorithms, data structures, and system design.', 180, 50, FALSE), +(19, 13, '2024-03-30 10:10:00', 'InterviewReport', 'Creative Video Production', 'Expect questions on how to manage video projects from pre-production to distribution.', 140, 38, FALSE), +(20, 14, '2024-04-01 13:00:00', 'InterviewReport', 'Creative Content Production Techniques', 'They wanted to know my approach to creative video production, including time management and collaborating with teams under tight deadlines.', 130, 35, FALSE), +(21, 15, '2024-04-05 14:30:00', 'InterviewReport', 'Robotics Engineering Solutions', 'They focused on advanced robotics engineering, including the integration of AI into robotic systems.', 190, 50, FALSE), +(22, 15, '2024-04-10 09:15:00', 'InterviewReport', 'Robotics Project Management', 'Expect questions on managing large-scale robotics projects, especially in an industrial setting.', 180, 48, FALSE), +(23, 16, '2024-04-15 10:45:00', 'InterviewReport', 'Financial Modeling Techniques', 'Expect in-depth questions about financial modeling, with a focus on real-world applications in the financial sector.', 170, 45, FALSE), +(24, 16, '2024-04-20 11:30:00', 'InterviewReport', 'Advanced Financial Analysis', 'They asked me to walk through complex financial analysis and forecasting techniques under tight deadlines.', 160, 42, FALSE), +(25, 17, '2024-04-25 16:00:00', 'InterviewReport', 'Automotive Engineering Challenges', 'The interview focused on automotive systems design and innovative testing methods.', 150, 40, FALSE), +(26, 18, '2024-04-30 09:40:00', 'InterviewReport', 'Vehicle System Design', 'They asked about the design of autonomous vehicle systems and the technologies driving them.', 140, 38, FALSE), +(27, 18, '2024-05-05 11:30:00', 'InterviewReport', 'Biotechnology Research and Development', 'Expect to discuss biotechnology innovations, particularly in gene editing and CRISPR technology.', 160, 45, FALSE), +(28, 19, '2024-05-10 14:15:00', 'InterviewReport', 'Innovations in Genetic Engineering', 'I had to talk about the latest advancements in genetic engineering and their real-world applications.', 170, 50, FALSE), +(29, 20, '2024-05-15 10:00:00', 'InterviewReport', 'Logistics and Supply Chain Optimization', 'Expect to be questioned on logistics challenges and supply chain optimization techniques under pressure.', 130, 35, FALSE), +(30, 21, '2024-05-20 15:00:00', 'InterviewReport', 'Supply Chain Process Optimization', 'They asked how I would optimize supply chain processes and improve operational efficiency.', 140, 38, FALSE); INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagged) VALUES (1, 2, NULL, 'This sounds like a fantastic experience! Thanks for sharing.', 10, FALSE), From 153b838cd7be492b7649330aac0bc5566351524b Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Fri, 6 Dec 2024 03:22:10 -0500 Subject: [PATCH 51/75] update flagged post manegment for admin --- api/.env | 2 +- api/backend/companies/companies_routes.py | 2 +- api/backend/reviews/reviews_routes.py | 132 ++++++++++++++++++ app/src/pages/3002_Flagged_Posts.py | 159 ++++++++++++++-------- database-files/10_coopPlatformDB.sql | 6 +- 5 files changed, 242 insertions(+), 59 deletions(-) diff --git a/api/.env b/api/.env index 14b676e4f4..66762c5f9f 100644 --- a/api/.env +++ b/api/.env @@ -3,4 +3,4 @@ DB_USER=root DB_HOST=db DB_PORT=3306 DB_NAME=CoopPlatform -MYSQL_ROOT_PASSWORD=CoopPCrazyS3 +MYSQL_ROOT_PASSWORD=CoopPCrazyS diff --git a/api/backend/companies/companies_routes.py b/api/backend/companies/companies_routes.py index b199bce40f..100252cce4 100644 --- a/api/backend/companies/companies_routes.py +++ b/api/backend/companies/companies_routes.py @@ -43,7 +43,7 @@ def get_feedback(): @companies.route('/companies/companies', methods=['PUT']) def update_company(): - current_app.logger.info('PUT /feedback route') + current_app.logger.info('PUT /companies route') try: companies_info = request.json diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index a17630d990..e4f095408d 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -17,6 +17,138 @@ # routes. reviews = Blueprint('reviews', __name__) +@reviews.route('/flagged', methods=['GET']) +def get_flaggedreview(): + try: + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT reviewID, reviewType, heading, content + FROM Reviews + WHERE isFlagged = TRUE; + ''') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + + except Exception as e: + current_app.logger.error(f"Error fetching flagged reviewss: {e}") + return {"error": "An error occurred while fetching flagged reviews"}, 500 + +@reviews.route('/approveflagged', methods=['PUT']) +def approve_flaggedreview(): + current_app.logger.info('PUT /reviews route') + try: + review_info = request.json + + if 'reviewID' not in review_info or 'isFlagged' not in review_info: + return {'error': 'Missing reviewID or isFlagged'}, 400 + + review_id = review_info['reviewID'] + if_flagged = review_info['isFlagged'] + + + query = ''' + UPDATE Reviews + SET isFlagged = %s + WHERE reviewID= %s; + ''' + + data = (if_flagged, review_id) + + cursor = db.get_db().cursor() + cursor.execute(query, data) + db.get_db().commit() + + return {'message': 'Reviews status updated successfully'}, 200 + + except KeyError as e: + current_app.logger.error(f"Missing key in request JSON: {str(e)}") + return {'error': f'Missing key: {str(e)}'}, 400 + except Exception as e: + current_app.logger.error(f"Error updating reviews: {str(e)}") + return {'error': 'An error occurred while updating reviews status'}, 500 + finally: + if 'cursor' in locals() and cursor: + cursor.close() + +@reviews.route('/editflagged', methods=['PUT']) +def edit_flaggedreview(): + current_app.logger.info('PUT /reviews route') + try: + review_info = request.json + + if 'reviewID' not in review_info or 'content' not in review_info: + return {'error': 'Missing reviewID or content'}, 400 + + review_id = review_info['reviewID'] + content = review_info['content'] + + + query = ''' + UPDATE Reviews + SET isFlagged = FALSE, + content = %s + WHERE reviewID= %s; + ''' + + data = (content, review_id) + + cursor = db.get_db().cursor() + cursor.execute(query, data) + db.get_db().commit() + + return {'message': 'Reviews status updated successfully'}, 200 + + except KeyError as e: + current_app.logger.error(f"Missing key in request JSON: {str(e)}") + return {'error': f'Missing key: {str(e)}'}, 400 + except Exception as e: + current_app.logger.error(f"Error updating reviews: {str(e)}") + return {'error': 'An error occurred while updating reviews status'}, 500 + finally: + if 'cursor' in locals() and cursor: + cursor.close() + +@reviews.route('/removeflagged', methods=['DELETE']) +def remove_flaggedreview(): + current_app.logger.info('DELETE /removeflagged route') + try: + review_info = request.json + + if 'reviewID' not in review_info: + return {'error': 'Missing reviewID'}, 400 + + review_id = review_info['reviewID'] + + try: + review_id = int(review_id) + except ValueError: + return {'error': 'Invalid reviewID format'}, 400 + + query = ''' + DELETE FROM Reviews + WHERE reviewID = %s; + ''' + data = (review_id,) + + cursor = db.get_db().cursor() + cursor.execute(query, data) + db.get_db().commit() + + return {'message': 'Review deleted successfully'}, 200 + + except KeyError as e: + current_app.logger.error(f"Missing key in request JSON: {str(e)}") + return {'error': f'Missing key: {str(e)}'}, 400 + except Exception as e: + current_app.logger.error(f"Error deleting review: {str(e)}") + return {'error': 'An error occurred while deleting the review.'}, 500 + finally: + if cursor is not None: + cursor.close() + @reviews.route('/submitReview', methods=['POST']) def add_review(): review_data = request.json diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py index 6b9aaa3d1b..c3731a3bfc 100644 --- a/app/src/pages/3002_Flagged_Posts.py +++ b/app/src/pages/3002_Flagged_Posts.py @@ -3,8 +3,9 @@ import pandas as pd import streamlit as st from streamlit_extras.app_logo import add_logo -import world_bank_data as wb +import requests import matplotlib.pyplot as plt +from datetime import datetime import numpy as np import plotly.express as px from modules.nav import SideBarLinks @@ -18,67 +19,117 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -import streamlit as st -import pandas as pd -from datetime import datetime +# get flagged posts +try: + reviews = requests.get("http://api:4000/r/flagged").json() +except: + st.write("Could not to conncet to database to get flagged reviews") -# Sample data for flagged posts -sample_data = [ - {"Post ID": 1, "Content": "This is a flagged post.", "Flag Reason": "Inappropriate Language", "History": []}, - {"Post ID": 2, "Content": "Another flagged post here.", "Flag Reason": "Spam", "History": []}, -] +if "reviews" not in st.session_state: + st.session_state.reviews = pd.DataFrame(reviews) -# Convert sample data to DataFrame -posts_df = pd.DataFrame(sample_data) +if "History" not in st.session_state: + st.session_state.History = [] + +if "timestamp" not in st.session_state: + st.session_state.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # Function to log actions -def log_action(post_id, action, reason=None): - for post in sample_data: - if post["Post ID"] == post_id: +def log_action(reviewID, action, reason=None): + for i in range(len(st.session_state.reviews)): + review = st.session_state.reviews.iloc[i] + if review["reviewID"] == reviewID: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - post["History"].append({"Action": action, "Reason": reason, "Timestamp": timestamp}) + #Hstory[reviewID] = {"Action": action, "Reason": reason, "Timestamp": timestamp} # Streamlit app st.title("Flagged Posts Review Interface") -# Display flagged posts +# Display flagged posts in a table st.subheader("Flagged Posts") - -for index, row in posts_df.iterrows(): - st.write(f"**Post ID:** {row['Post ID']}") - st.write(f"**Content:** {row['Content']}") - st.write(f"**Flag Reason:** {row['Flag Reason']}") - - # Buttons for actions - col1, col2, col3 = st.columns(3) - - with col1: - if st.button(f"Approve Post {row['Post ID']}"): - log_action(row['Post ID'], "Approved") - st.success(f"Post {row['Post ID']} approved.") - - with col2: - if st.button(f"Edit Post {row['Post ID']}"): - new_content = st.text_area(f"Edit Content for Post {row['Post ID']}", row['Content']) - if st.button(f"Save Changes to Post {row['Post ID']}"): - posts_df.loc[index, "Content"] = new_content - log_action(row['Post ID'], "Edited", f"Updated content to: {new_content}") - st.success(f"Post {row['Post ID']} updated.") - - with col3: - if st.button(f"Remove Post {row['Post ID']}"): - log_action(row['Post ID'], "Removed") - st.warning(f"Post {row['Post ID']} removed.") - - # Display action history - st.write("**Action History:**") - history = row['History'] - if history: - for entry in history: - st.write(f"- {entry['Timestamp']} - {entry['Action']} ({entry.get('Reason', 'No Reason')})") +selected_post_id = st.selectbox( + "Select a review to review:", + st.session_state.reviews["reviewID"], + format_func=lambda x: f"Review {x}: {st.session_state.reviews.loc[st.session_state.reviews['reviewID'] == x, 'heading'].values[0]}" +) + + +# Show details of the selected post +selected_post = st.session_state.reviews[st.session_state.reviews["reviewID"] == selected_post_id].iloc[0] +st.write(f"**Review ID:** {selected_post['reviewID']}") +st.write(f"**Content:** {selected_post['content']}") +st.write(f"**Review Type:** {selected_post['reviewType']}") + +# Action options +st.subheader("Actions") +action = st.radio("Select an action to perform:", ["None", "Approve", "Edit", "Remove"],index = 0) +# Execute selected action + +if action == "Approve": + st.session_state.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + data = { + "reviewID": selected_post_id, + "isFlagged": False + } + + response = requests.put("http://api:4000/r/approveflagged", json=data) + + # reflect the response + if response.status_code == 200: + print("Success:", response.json()) else: - st.write("No actions taken yet.") - - st.divider() - -st.write("**Note:** This interface uses sample data. Replace with actual data for production.") + print("Error:", response.status_code, response.json()) + st.success(f"Review {selected_post_id} approved.") + + + +elif action == "Edit": + new_content = st.text_area("Edit Content", selected_post['content']) + if st.button("Save Changes"): + st.session_state.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + st.session_state.reviews.loc[st.session_state.reviews["reviewID"] == selected_post_id, "Content"] = new_content + data = { + "reviewID": selected_post_id, + "content": new_content + } + + response = requests.put("http://api:4000/r/editflagged", json=data) + + # reflect the response + if response.status_code == 200: + print("Success:", response.json()) + else: + print("Error:", response.status_code, response.json()) + st.success(f"Post {selected_post_id} updated.") + +elif action == "Remove": + st.session_state.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + data = { + "reviewID": selected_post_id, + } + response = requests.delete("http://api:4000/r/removeflagged", json=data) + if response.status_code == 200: + print("Success:", response.json()) + else: + try: + error_message = response.json() + except ValueError: + error_message = "No error details provided" + print("Error:", response.status_code, error_message) + st.warning(f"Review {selected_post_id} removed.") + +st.session_state.History.append(f"- {st.session_state.timestamp} - Review {selected_post_id} - {action}") +# Display action history +st.subheader("Action History") +for entry in st.session_state.History: + st.write(entry) + +''' +#st.write(history) +if selected_post_id is not Nonest.session_state.History[selected_post_id]: + history = st.session_state.History[selected_post_id] + for entry in history: + st.write(f"- {entry['Timestamp']} - {entry['Action']} ({entry.get('Reason', 'No Reason')})") +else: + st.write("No actions taken yet.") +''' diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index e780f0955c..0d7aaaba2b 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -86,8 +86,8 @@ CREATE TABLE IF NOT EXISTS Reviews ( views INT DEFAULT 0, likes INT DEFAULT 0, isFlagged BOOLEAN DEFAULT FALSE, - FOREIGN KEY (userID) REFERENCES User(userID), - FOREIGN KEY (roleID) REFERENCES Role(roleID) + FOREIGN KEY (userID) REFERENCES User(userID) ON DELETE CASCADE, + FOREIGN KEY (roleID) REFERENCES Role(roleID) ON DELETE CASCADE ); @@ -102,7 +102,7 @@ CREATE TABLE IF NOT EXISTS Comments ( content TEXT, likes INT DEFAULT 0, isFlagged BOOLEAN DEFAULT FALSE, - FOREIGN KEY (reviewID) REFERENCES Reviews(reviewID), + FOREIGN KEY (reviewID) REFERENCES Reviews(reviewID) ON DELETE CASCADE, FOREIGN KEY (userID) REFERENCES User(userID), FOREIGN KEY (parentCommentID) REFERENCES Comments(commentID) ); From a083290ecbf242e131ec3966f1fb34a61ed3f2f3 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Fri, 6 Dec 2024 03:56:04 -0500 Subject: [PATCH 52/75] update admin dashboard --- api/backend/reviews/reviews_routes.py | 37 ++++++++++++ app/src/pages/3001_Admin_Dashboard.py | 77 +++++++++++++++++++------ app/src/pages/3002_Flagged_Posts.py | 8 --- database-files/12_CoopPlatform_Data.sql | 14 ++--- 4 files changed, 104 insertions(+), 32 deletions(-) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index e4f095408d..fb87a42900 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -16,6 +16,42 @@ # Create a new Blueprint object, which is a collection of # routes. reviews = Blueprint('reviews', __name__) +@reviews.route('/reviews', methods=['GET']) +def get_reviews(): + try: + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT * + FROM Reviews; + ''') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + + except Exception as e: + current_app.logger.error(f"Error fetching reviews: {e}") + return {"error": "An error occurred while fetching reviews"}, 500 + +@reviews.route('/comments', methods=['GET']) +def get_comments(): + try: + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT * + FROM Comments + WHERE isFlagged = TRUE; + ''') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + + except Exception as e: + current_app.logger.error(f"Error fetching comments: {e}") + return {"error": "An error occurred while fetching comments"}, 500 @reviews.route('/flagged', methods=['GET']) def get_flaggedreview(): @@ -149,6 +185,7 @@ def remove_flaggedreview(): if cursor is not None: cursor.close() + @reviews.route('/submitReview', methods=['POST']) def add_review(): review_data = request.json diff --git a/app/src/pages/3001_Admin_Dashboard.py b/app/src/pages/3001_Admin_Dashboard.py index 950a074139..fc1ef7b775 100644 --- a/app/src/pages/3001_Admin_Dashboard.py +++ b/app/src/pages/3001_Admin_Dashboard.py @@ -1,5 +1,6 @@ import logging logger = logging.getLogger(__name__) +import requests import pandas as pd import streamlit as st from streamlit_extras.app_logo import add_logo @@ -18,24 +19,66 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) +# get flagged reviews +try: + flaggedreviews = requests.get("http://api:4000/r/flagged").json() +except: + st.write("Could not to conncet to database to get flagged reviews") + +if "flaggedreviews" not in st.session_state: + st.session_state.flaggedreviews = pd.DataFrame(flaggedreviews) + +# get reviews +try: + reviews = requests.get("http://api:4000/r/reviews").json() +except: + st.write("Could not to conncet to database to get flagged reviews") + +if "reviews" not in st.session_state: + st.session_state.reviews = pd.DataFrame(reviews) + + +# get comments +try: + comments = requests.get("http://api:4000/r/comments").json() +except: + st.write("Could not to conncet to database to get comments") + +if "comments" not in st.session_state: + st.session_state.comments = pd.DataFrame(comments) + + +# Sample data for demonstration +user_activity_data = { + "Metric": ["Total Reviews", "Flagged Reviews", "Flagged Comments"], + "Count": [len(st.session_state.reviews), len(st.session_state.flaggedreviews), len(st.session_state.comments)], +} + + + +# Title and description +st.title("User Activity Dashboard") +st.write("An interface to manage user activity metrics, flagged reviews, and flagged comments.") + +# Display user activity metrics +st.subheader("User Activity Metrics") +metrics_df = pd.DataFrame(user_activity_data) +st.table(metrics_df) + + +# Filterable list of flagged reviews +st.subheader("Flagged Comments List") + +# Add filters +user_filter = st.selectbox("Filter by User ID", sorted(st.session_state.comments["userID"].unique())) +user_df = st.session_state.comments[st.session_state.comments["userID"]==user_filter ] +st.dataframe(user_df) +review_filter = st.selectbox("Filter by Review ID", sorted(st.session_state.comments["reviewID"].unique())) +review_df = st.session_state.comments[st.session_state.comments["reviewID"]==review_filter] +st.dataframe(review_df) + + -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) - st.pyplot(test_plot) -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) \ No newline at end of file diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py index c3731a3bfc..55f5397aaa 100644 --- a/app/src/pages/3002_Flagged_Posts.py +++ b/app/src/pages/3002_Flagged_Posts.py @@ -34,14 +34,6 @@ if "timestamp" not in st.session_state: st.session_state.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") -# Function to log actions -def log_action(reviewID, action, reason=None): - for i in range(len(st.session_state.reviews)): - review = st.session_state.reviews.iloc[i] - if review["reviewID"] == reviewID: - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - #Hstory[reviewID] = {"Action": action, "Reason": reason, "Timestamp": timestamp} - # Streamlit app st.title("Flagged Posts Review Interface") diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index de5fc087c7..05f55976cc 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -266,12 +266,12 @@ INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagg (2, 4, NULL, 'Do you think the communication issue is company-wide?', 8, FALSE), (2, 1, 4, 'Yes, I think it varies by team, but it’s something to improve.', 6, FALSE), (3, 5, NULL, 'Aerospace is such an exciting field. How was the workload?', 12, FALSE), -(4, 6, NULL, 'I’ve been considering applying here. Any tips for getting in?', 15, FALSE), +(4, 6, NULL, 'I’ve been considering applying here. Any tips for getting in?', 15, TRUE), (4, 2, 6, 'Focus on renewable energy projects in your portfolio.', 7, FALSE), (5, 7, NULL, 'I love collaborative environments. Sounds like a great role.', 4, FALSE), (6, 8, NULL, 'Heavy workloads can be tough. Was the management supportive?', 9, FALSE), -(6, 9, 8, 'They were supportive but often stretched thin.', 3, FALSE), -(7, 10, NULL, 'Smart cities are the future. How innovative were the projects?', 13, FALSE), +(6, 9, 8, 'They were supportive but often stretched thin.', 3, TRUE), +(7, 10, NULL, 'Smart cities are the future. How innovative were the projects?', 13, TRUE), (8, 11, NULL, 'What kind of growth opportunities were you hoping for?', 6, FALSE), (8, 3, 11, 'Leadership roles or cross-functional projects.', 4, FALSE), (9, 12, NULL, 'Tech companies often have dynamic environments. Did you feel valued?', 11, FALSE), @@ -283,14 +283,14 @@ INSERT INTO Comments (reviewID, userID, parentCommentID, content, likes, isFlagg (14, 18, NULL, 'How innovative was the genetic research you were involved in?', 20, FALSE), (14, 19, 18, 'Very cutting-edge, especially in CRISPR technology.', 12, FALSE), (15, 20, NULL, 'Efficient logistics management is key to success.', 9, FALSE), -(16, 21, NULL, 'What kind of tools were used for cybersecurity?', 11, FALSE), +(16, 21, NULL, 'What kind of tools were used for cybersecurity?', 11, TRUE), (16, 22, 21, 'Mostly Splunk, Wireshark, and custom tools.', 5, FALSE), (17, 23, NULL, 'Tight deadlines can be tough. How was the work-life balance?', 7, FALSE), -(18, 24, NULL, 'Eco-friendly construction is inspiring. What projects stood out?', 14, FALSE), +(18, 24, NULL, 'Eco-friendly construction is inspiring. What projects stood out?', 14, TRUE), (19, 25, NULL, 'VR development is fascinating. What applications did you focus on?', 17, FALSE), (19, 26, 25, 'Medical training simulations. Very impactful.', 10, FALSE), -(20, 27, NULL, 'Gourmet food development sounds interesting! How creative was it?', 8, FALSE), -(21, 28, NULL, 'Interior design is so rewarding. What was your favorite project?', 13, FALSE); +(20, 27, NULL, 'Gourmet food development sounds interesting! How creative was it?', 8, TRUE), +(21, 28, NULL, 'Interior design is so rewarding. What was your favorite project?', 13, TRUE); INSERT INTO Badges (badgeName) VALUES From 96d074524c710a3b642723f8e5a66dadc5a012ec Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Fri, 6 Dec 2024 04:45:53 -0500 Subject: [PATCH 53/75] update analytics for admin --- api/backend/companies/companies_routes.py | 48 ++++++++++++++- app/src/CoopPlatform.db | 0 app/src/pages/3002_Flagged_Posts.py | 9 --- app/src/pages/3005_Analytics_and_Trends.py | 68 ++++++++++++++++------ 4 files changed, 98 insertions(+), 27 deletions(-) create mode 100644 app/src/CoopPlatform.db diff --git a/api/backend/companies/companies_routes.py b/api/backend/companies/companies_routes.py index 100252cce4..6c91fe9cae 100644 --- a/api/backend/companies/companies_routes.py +++ b/api/backend/companies/companies_routes.py @@ -18,7 +18,7 @@ #------------------------------------------------------------ # Get all feedback from the system @companies.route('/companies', methods=['GET']) -def get_feedback(): +def get_companies(): try: with db.get_db().cursor() as cursor: cursor.execute(''' @@ -117,4 +117,50 @@ def update_roles(): finally: if 'cursor' in locals() and cursor: cursor.close() + +@companies.route('/industries', methods=['GET']) +def get_industries(): + try: + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT count(C.companyID) AS NumCompany, I.name AS Industry + FROM Companies C JOIN CompanyIndustry CI + ON CI.companyID = C.companyID JOIN Industries I + ON I.industryID = CI.industryID + GROUP BY I.industryID + ORDER BY I.industryID + ''') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + + except Exception as e: + current_app.logger.error(f"Error fetching companies: {e}") + return {"error": "An error occurred while fetching companies"}, 500 + +@companies.route('/reviews', methods=['GET']) +def get_reviews(): + try: + with db.get_db().cursor() as cursor: + cursor.execute(''' + SELECT count(R.reviewID) AS NumReviews, I.name AS Industry + FROM Companies C JOIN CompanyIndustry CI + ON CI.companyID = C.companyID JOIN Industries I + ON I.industryID = CI.industryID JOIN Role RO + ON RO.CompanyID = C.CompanyID JOIN Reviews R + ON RO.roleID = R.roleID + GROUP BY I.industryID + ORDER BY I.industryID + ''') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + + except Exception as e: + current_app.logger.error(f"Error fetching reviews: {e}") + return {"error": "An error occurred while fetching reviews"}, 500 diff --git a/app/src/CoopPlatform.db b/app/src/CoopPlatform.db new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py index 55f5397aaa..2992b956b8 100644 --- a/app/src/pages/3002_Flagged_Posts.py +++ b/app/src/pages/3002_Flagged_Posts.py @@ -116,12 +116,3 @@ for entry in st.session_state.History: st.write(entry) -''' -#st.write(history) -if selected_post_id is not Nonest.session_state.History[selected_post_id]: - history = st.session_state.History[selected_post_id] - for entry in history: - st.write(f"- {entry['Timestamp']} - {entry['Action']} ({entry.get('Reason', 'No Reason')})") -else: - st.write("No actions taken yet.") -''' diff --git a/app/src/pages/3005_Analytics_and_Trends.py b/app/src/pages/3005_Analytics_and_Trends.py index f9e6cd55fc..f72539c7d6 100644 --- a/app/src/pages/3005_Analytics_and_Trends.py +++ b/app/src/pages/3005_Analytics_and_Trends.py @@ -1,5 +1,6 @@ import logging logger = logging.getLogger(__name__) +import requests import pandas as pd import streamlit as st from streamlit_extras.app_logo import add_logo @@ -17,25 +18,58 @@ # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") +import streamlit as st +import pandas as pd +import matplotlib.pyplot as plt + + +# get industries +try: + industries = requests.get("http://api:4000/c/industries").json() +except: + st.write("Could not to conncet to database to get industries") + +if "industries" not in st.session_state: + st.session_state.industries = pd.DataFrame(industries) + +# get reviews +try: + reviews = requests.get("http://api:4000/c/reviews").json() +except: + st.write("Could not to conncet to database to get reviews") + +if "industries" not in st.session_state: + st.session_state.industries = pd.DataFrame(industries) +if "reviews" not in st.session_state: + st.session_state.reviews = pd.DataFrame(reviews) + +# Title +st.title("Trends in Student Reviews and Companies") +st.subheader("Trend Data") +fig, ax = plt.subplots(figsize=(10, 6)) +ax.plot(st.session_state.reviews["Industry"], st.session_state.reviews['NumReviews'], label="reviews", marker="o") +ax.plot(st.session_state.industries["Industry"], st.session_state.industries['NumCompany'], label="Companies", marker="o") +ax.set_ylabel("Count") +ax.set_title("Trends by Category") +ax.set_xticklabels(st.session_state.industries["Industry"], rotation=45, ha="right") +ax.legend() +ax.grid(True) +st.pyplot(fig) + +# Actionable Insights +st.subheader("Actionable Insights") +most_companies = st.session_state.industries.sort_values("NumCompany").iloc[-1] +st.write(f"**Industry with Most Companies**: {most_companies['Industry']} ({most_companies['NumCompany']} companies)") + + +most_reviews = st.session_state.reviews.sort_values("NumReviews").iloc[-1] +st.write(f"**Industry with Most Reviews**: {most_reviews['Industry']} ({most_reviews['NumReviews']} reviews)") -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) +# Display Data Table +df = pd.merge(st.session_state.industries,st.session_state.reviews, on = "Industry") - st.pyplot(test_plot) +st.subheader("Data Table") +st.dataframe(df) -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) \ No newline at end of file From a181d121411884393649a3a0fc7241b235e08454 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Fri, 6 Dec 2024 11:09:38 -0500 Subject: [PATCH 54/75] Spelling mistake --- app/src/pages/3005_Analytics_and_Trends.py | 88 +++++++++++----------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/app/src/pages/3005_Analytics_and_Trends.py b/app/src/pages/3005_Analytics_and_Trends.py index f72539c7d6..411e9b5a7f 100644 --- a/app/src/pages/3005_Analytics_and_Trends.py +++ b/app/src/pages/3005_Analytics_and_Trends.py @@ -4,72 +4,72 @@ import pandas as pd import streamlit as st from streamlit_extras.app_logo import add_logo -import world_bank_data as wb import matplotlib.pyplot as plt -import numpy as np -import plotly.express as px -from modules.nav import SideBarLinks -# Call the SideBarLinks from the nav module in the modules directory +# Safe initialization of session state variables +if "first_name" not in st.session_state: + st.session_state.first_name = "Guest" + +# Call the SideBarLinks from the nav module +from modules.nav import SideBarLinks SideBarLinks() -# set the header of the page +# Set the header of the page st.header('View Analytics and Trends') - -# You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") -import streamlit as st -import pandas as pd -import matplotlib.pyplot as plt - -# get industries +# Fetch industries +industries = [] try: industries = requests.get("http://api:4000/c/industries").json() -except: - st.write("Could not to conncet to database to get industries") - +except Exception as e: + st.write(f"Error: {e}") + st.write("Could not connect to database to get industries.") if "industries" not in st.session_state: st.session_state.industries = pd.DataFrame(industries) - -# get reviews + +# Fetch reviews +reviews = [] try: reviews = requests.get("http://api:4000/c/reviews").json() -except: - st.write("Could not to conncet to database to get reviews") - -if "industries" not in st.session_state: - st.session_state.industries = pd.DataFrame(industries) +except Exception as e: + st.write(f"Error: {e}") + st.write("Could not connect to database to get reviews.") if "reviews" not in st.session_state: st.session_state.reviews = pd.DataFrame(reviews) # Title st.title("Trends in Student Reviews and Companies") st.subheader("Trend Data") -fig, ax = plt.subplots(figsize=(10, 6)) -ax.plot(st.session_state.reviews["Industry"], st.session_state.reviews['NumReviews'], label="reviews", marker="o") -ax.plot(st.session_state.industries["Industry"], st.session_state.industries['NumCompany'], label="Companies", marker="o") -ax.set_ylabel("Count") -ax.set_title("Trends by Category") -ax.set_xticklabels(st.session_state.industries["Industry"], rotation=45, ha="right") -ax.legend() -ax.grid(True) -st.pyplot(fig) + +# Plot trends if data is valid +if not st.session_state.industries.empty and not st.session_state.reviews.empty: + fig, ax = plt.subplots(figsize=(10, 6)) + ax.plot(st.session_state.reviews["Industry"], st.session_state.reviews['NumReviews'], label="reviews", marker="o") + ax.plot(st.session_state.industries["Industry"], st.session_state.industries['NumCompany'], label="Companies", marker="o") + ax.set_ylabel("Count") + ax.set_title("Trends by Category") + ax.set_xticklabels(st.session_state.industries["Industry"], rotation=45, ha="right") + ax.legend() + ax.grid(True) + st.pyplot(fig) +else: + st.write("Insufficient data to display trends.") # Actionable Insights st.subheader("Actionable Insights") -most_companies = st.session_state.industries.sort_values("NumCompany").iloc[-1] -st.write(f"**Industry with Most Companies**: {most_companies['Industry']} ({most_companies['NumCompany']} companies)") - - -most_reviews = st.session_state.reviews.sort_values("NumReviews").iloc[-1] -st.write(f"**Industry with Most Reviews**: {most_reviews['Industry']} ({most_reviews['NumReviews']} reviews)") +if not st.session_state.industries.empty: + most_companies = st.session_state.industries.sort_values("NumCompany").iloc[-1] + st.write(f"**Industry with Most Companies**: {most_companies['Industry']} ({most_companies['NumCompany']} companies)") +if not st.session_state.reviews.empty: + most_reviews = st.session_state.reviews.sort_values("NumReviews").iloc[-1] + st.write(f"**Industry with Most Reviews**: {most_reviews['Industry']} ({most_reviews['NumReviews']} reviews)") # Display Data Table -df = pd.merge(st.session_state.industries,st.session_state.reviews, on = "Industry") - -st.subheader("Data Table") -st.dataframe(df) - - +if "Industry" in st.session_state.industries and "Industry" in st.session_state.reviews: + df = pd.merge(st.session_state.industries, st.session_state.reviews, on="Industry") + st.subheader("Data Table") + st.dataframe(df) +else: + st.write("Data table cannot be displayed due to missing columns.") From fe2ffdd02bd5d51bd1149e3c0ccfe4e4a61d0487 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Fri, 6 Dec 2024 12:32:53 -0500 Subject: [PATCH 55/75] editing reviews works, also updated the review display. added .env to git ignore. --- .gitignore | 1 + api/backend/reviews/reviews_routes.py | 7 ++-- app/src/pages/2001_Review_Form.py | 6 +-- app/src/pages/2002_My_Reviews.py | 37 +++++++++++++---- .../300_System_Administrator_Home copy.py | 40 +++++++++++++++++++ 5 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 app/src/pages/300_System_Administrator_Home copy.py diff --git a/.gitignore b/.gitignore index 565b651700..76db9a8b51 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ secrets.toml __pycache__ secrets/ +.env .env.local \ No newline at end of file diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index fb87a42900..8dbcf6a4c5 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -382,16 +382,17 @@ def update_review(): reviewID = data.get('reviewID') heading = data.get('heading') content = data.get('content') - reviewType = data.get('reviewType') + + print("NEW CONTENT: ", content) query = ''' UPDATE Reviews - SET heading = %s, content = %s, reviewType = %s + SET heading = %s, content = %s WHERE reviewID = %s; ''' cursor = db.get_db().cursor() - cursor.execute(query, (heading, content, reviewType, reviewID)) + cursor.execute(query, (heading, content, reviewID)) db.get_db().commit() response = make_response(jsonify({"message": "Review updated successfully"})) diff --git a/app/src/pages/2001_Review_Form.py b/app/src/pages/2001_Review_Form.py index 62b63b7665..ab422d5457 100644 --- a/app/src/pages/2001_Review_Form.py +++ b/app/src/pages/2001_Review_Form.py @@ -79,11 +79,11 @@ def fetch_comments(review_id): # Pre-fill the form with role info st.write(f"Reviewing role: {selected_role_name} at {selected_company_name}") - + + new_review_type = st.selectbox("Review Type", ["Experience", "InterviewReport", "Feedback", "Other"]) new_heading = st.text_input("Review Heading") new_content = st.text_area("Content") - new_review_type = st.selectbox("Review Type", ["Experience", "InterviewReport", "Feedback", "Other"]) - + submit_button = st.form_submit_button("Submit Review") # Handle form submission diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index 1f2c556eef..4e50c94cbf 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -49,6 +49,10 @@ def fetch_comments(review_id): return [] # If there are reviews, display them +# Display the edit form for the currently selected review +if "editing_review_id" not in st.session_state: + st.session_state["editing_review_id"] = None + if reviews: st.subheader("Your Reviews") for review in reviews: @@ -58,11 +62,12 @@ def fetch_comments(review_id): # Display review details st.markdown(f"### {review['heading']} ({review['reviewType']})") - st.markdown(f"**Published At:** {review['publishedAt']}") - st.markdown(f"**Views:** {review['views']} | **Likes:** {review['likes']}") st.markdown(f"**Role:** {role_name} at **{company_name}**") st.markdown(f"**Content:** {review['content']}") + st.markdown(f"**Views:** {review['views']} | **Likes:** {review['likes']}") + + st.markdown(f"**Published At:** {review['publishedAt']}") # Fetch and display comments comments = fetch_comments(review['reviewID']) st.markdown("#### Comments:") @@ -72,18 +77,26 @@ def fetch_comments(review_id): else: st.markdown("*No comments yet.*") + + # Display the edit button - edit_button = st.button(f"Edit Review {review['reviewID']}") + edit_button = st.button( + f"Edit Review {review['reviewID']}", + key=f"edit_button_{review['reviewID']}" + ) if edit_button: - # If the button is clicked, show the edit form - with st.form(key=f'edit_review_{review["reviewID"]}'): + # Set the review ID to session state for editing + st.session_state["editing_review_id"] = review["reviewID"] + + # If this review is being edited, display the edit form + if st.session_state["editing_review_id"] == review["reviewID"]: + with st.form(key=f'edit_review_form_{review["reviewID"]}'): st.subheader("Edit this Review") # Pre-fill the form with the current review details new_heading = st.text_input("Heading", value=review["heading"]) new_content = st.text_area("Content", value=review["content"]) - new_review_type = st.selectbox("Review Type", ["Experience", "Feedback", "Other"], index=["Experience", "Feedback", "Other"].index(review["reviewType"])) submit_button = st.form_submit_button(label="Update Review") @@ -93,16 +106,24 @@ def fetch_comments(review_id): "reviewID": review["reviewID"], "heading": new_heading, "content": new_content, - "reviewType": new_review_type } try: - update_response = requests.put(f'http://api:4000/r/updateReview', json=update_review_data) + update_response = requests.put( + f'http://api:4000/r/updateReview', + json=update_review_data + ) update_response.raise_for_status() st.success("Review updated successfully!") + # Reset the editing state + st.session_state["editing_review_id"] = None except requests.exceptions.RequestException as e: st.error(f"Failed to update review: {e}") + # Add a cancel button to stop editing + if st.button(f"Done {review['reviewID']}", key=f"cancel_button_{review['reviewID']}"): + st.session_state["editing_review_id"] = None + st.markdown("---") else: st.info("No reviews found. Start by adding your first review!") diff --git a/app/src/pages/300_System_Administrator_Home copy.py b/app/src/pages/300_System_Administrator_Home copy.py new file mode 100644 index 0000000000..b3c9d582b1 --- /dev/null +++ b/app/src/pages/300_System_Administrator_Home copy.py @@ -0,0 +1,40 @@ +import logging +logger = logging.getLogger(__name__) +import streamlit as st +from modules.nav import SideBarLinks + +st.set_page_config(layout = 'wide') + +# Show appropriate sidebar links for the role of the currently logged in user +SideBarLinks() + +st.title(f"Welcome System Administrator, {st.session_state['first_name']}.") +st.write('') +st.write('') +st.write('### What would you like to do today?') + +if st.button('View Admin Dashboard', + type='primary', + use_container_width=True): + st.switch_page('pages/3001_Admin_Dashboard.py') + +if st.button('View and Moderate Flagged Posts', + type='primary', + use_container_width=True): + st.switch_page('pages/3002_Flagged_Posts.py') + +if st.button('Edit and Update Company Profiles', + type='primary', + use_container_width=True): + st.switch_page('pages/3003_Company_Profiles.py') + +if st.button('View and Categorize User Feedback', + type='primary', + use_container_width=True): + st.switch_page('pages/3004_User_Feedback.py') + +if st.button('View Analytics and Trends', + type='primary', + use_container_width=True): + st.switch_page('pages/3005_Analytics_and_Trends.py') + From 73fce3119f196495a4803d5481b3eb4d357900b2 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Fri, 6 Dec 2024 12:40:34 -0500 Subject: [PATCH 56/75] updated display for reviews --- app/src/pages/2002_My_Reviews.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index 4e50c94cbf..a728975b88 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -15,9 +15,6 @@ # Set the header of the page st.header('My Reviews') -# Display personalized greeting -st.write(f"### Hi, {st.session_state['first_name']}!") - # Fetch the user's reviews try: response = requests.get(f'http://api:4000/r/reviewsByUser/{st.session_state["id"]}') @@ -54,16 +51,16 @@ def fetch_comments(review_id): st.session_state["editing_review_id"] = None if reviews: - st.subheader("Your Reviews") for review in reviews: with st.container(): # Fetch role and company details role_name, company_name = fetch_role_and_company(review['roleID']) # Display review details - st.markdown(f"### {review['heading']} ({review['reviewType']})") + st.markdown(f"### {review['reviewType']}") # Review type in bold above the title st.markdown(f"**Role:** {role_name} at **{company_name}**") - st.markdown(f"**Content:** {review['content']}") + st.markdown(f"#### {review['heading']}") + st.markdown(f"{review['content']}") st.markdown(f"**Views:** {review['views']} | **Likes:** {review['likes']}") From 16a03a323b6ab2e0e6117203a17ac183ca17c485 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Fri, 6 Dec 2024 12:51:55 -0500 Subject: [PATCH 57/75] added nav bar links for searcher and reviewer --- app/src/Home.py | 2 ++ app/src/modules/nav.py | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/src/Home.py b/app/src/Home.py index 61b08eb166..3d9df7d8d2 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -59,6 +59,8 @@ st.session_state['role'] = 'Co-Op reviewer' st.session_state['id'] = '1' st.session_state['first_name'] = 'Riley' + + logger.info("Logging in as Co Op Reviewer") st.switch_page('pages/200_CoOp_Reviewer_Home.py') if st.button('Act as System Administrator', diff --git a/app/src/modules/nav.py b/app/src/modules/nav.py index 327181105e..8090d2698d 100644 --- a/app/src/modules/nav.py +++ b/app/src/modules/nav.py @@ -47,6 +47,16 @@ def ClassificationNav(): "pages/13_Classification.py", label="Classification Demo", icon="🌺" ) +#### ------------------------ Co-Op Searcher Role ------------------------ +def SearcherPageNav(): + st.sidebar.page_link("pages/100_CoOp_Searcher_Home.py", label="Co-Op Searcher", icon="🔍") + + +#### ------------------------ Co Op Reviewer Role ------------------------ +def ReviewerPageNav(): + st.sidebar.page_link("pages/200_CoOp_Reviewer_Home.py", label="Co-Op Reviewer", icon="📝") + + #### ------------------------ System Admin Role ------------------------ def AdminPageNav(): @@ -81,10 +91,12 @@ def SideBarLinks(show_home=False): MapDemoNav() # If the user role is usaid worker, show the Api Testing page - if st.session_state["role"] == "usaid_worker": - PredictionNav() - ApiTestNav() - ClassificationNav() + if st.session_state["role"] == "Co-Op reviewer": + ReviewerPageNav() + + # If the user role is usaid worker, show the Api Testing page + if st.session_state["role"] == "Co-Op searcher": + SearcherPageNav() # If the user is an administrator, give them access to the administrator pages if st.session_state["role"] == "administrator": From ac0816a8b932819fbd201602149a8ea215858100 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Fri, 6 Dec 2024 14:20:55 -0500 Subject: [PATCH 58/75] Changed comments in DB to cascade delete to add Ability to delete reviews --- api/backend/reviews/reviews_routes.py | 29 +++++++++++++++++++++++++++ app/src/pages/2002_My_Reviews.py | 19 ++++++++++++++++++ database-files/10_coopPlatformDB.sql | 4 ++-- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index 8dbcf6a4c5..10a724db5d 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -375,6 +375,35 @@ def get_comments_by_review(reviewID): response.status_code = 200 return response +@reviews.route('/deleteReview/', methods=['DELETE']) +def delete_review(review_id): + try: + # Define the query to delete the review + query = f''' + DELETE FROM Reviews + WHERE reviewID = {review_id}; + ''' + + # Get the database connection and execute the query + cursor = db.get_db().cursor() + cursor.execute(query) + db.get_db().commit() + + # Check if any row was affected (deleted) + if cursor.rowcount > 0: + response = make_response(jsonify({"message": "Review deleted successfully"})) + response.status_code = 200 + else: + response = make_response(jsonify({"message": "Review not found"})) + response.status_code = 404 + except Exception as e: + # Log the exception and return a 500 error + logger.error(f"Error deleting review: {e}") + response = make_response(jsonify({"message": "Internal Server Error", "error": str(e)})) + response.status_code = 500 + + return response + @reviews.route('/updateReview', methods=['PUT']) def update_review(): data = request.get_json() diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index a728975b88..0b8170ce51 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -121,6 +121,25 @@ def fetch_comments(review_id): if st.button(f"Done {review['reviewID']}", key=f"cancel_button_{review['reviewID']}"): st.session_state["editing_review_id"] = None + # Add a Delete button + delete_button = st.button(f"Delete Review {review['reviewID']}", key=f"delete_button_{review['reviewID']}") + + if delete_button: + # Confirm deletion before making the API request + confirm_delete = "Delete" + + if confirm_delete == "Delete": + try: + delete_response = requests.delete( + f'http://api:4000/r/deleteReview/{review["reviewID"]}' + ) + delete_response.raise_for_status() + st.success("Review deleted successfully!") + # Optionally, refresh the page or remove the deleted review from the list + reviews = [rev for rev in reviews if rev["reviewID"] != review["reviewID"]] + except requests.exceptions.RequestException as e: + st.error(f"Failed to delete review: {e}") + st.markdown("---") else: st.info("No reviews found. Start by adding your first review!") diff --git a/database-files/10_coopPlatformDB.sql b/database-files/10_coopPlatformDB.sql index 0d7aaaba2b..0ecf2b1405 100644 --- a/database-files/10_coopPlatformDB.sql +++ b/database-files/10_coopPlatformDB.sql @@ -90,7 +90,6 @@ CREATE TABLE IF NOT EXISTS Reviews ( FOREIGN KEY (roleID) REFERENCES Role(roleID) ON DELETE CASCADE ); - -- Create Comments table CREATE TABLE IF NOT EXISTS Comments ( commentID INT AUTO_INCREMENT PRIMARY KEY, @@ -104,10 +103,11 @@ CREATE TABLE IF NOT EXISTS Comments ( isFlagged BOOLEAN DEFAULT FALSE, FOREIGN KEY (reviewID) REFERENCES Reviews(reviewID) ON DELETE CASCADE, FOREIGN KEY (userID) REFERENCES User(userID), - FOREIGN KEY (parentCommentID) REFERENCES Comments(commentID) + FOREIGN KEY (parentCommentID) REFERENCES Comments(commentID) ON DELETE CASCADE ); + -- Create Badges table CREATE TABLE IF NOT EXISTS Badges ( badgeID INT AUTO_INCREMENT PRIMARY KEY, From 3aebe2b643156462c0123c2275870f178872363f Mon Sep 17 00:00:00 2001 From: sevensrig Date: Fri, 6 Dec 2024 14:31:45 -0500 Subject: [PATCH 59/75] Changed front-end look of searcher pages --- api/backend/coop_searcher/searcher_routes.py | 20 +++++++++++++++---- app/src/Home.py | 6 +++--- .../pages/1001_Company_Position_Reviews.py | 2 +- app/src/pages/1002_Interview_Information.py | 2 +- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/api/backend/coop_searcher/searcher_routes.py b/api/backend/coop_searcher/searcher_routes.py index e6ec9ce491..76aecc076e 100644 --- a/api/backend/coop_searcher/searcher_routes.py +++ b/api/backend/coop_searcher/searcher_routes.py @@ -45,7 +45,9 @@ def get_reviews_for_company(company_name): # Use parameterized query to prevent SQL injection query = ''' SELECT - rv.content + rv.content, + r.roleName, + rv.reviewType FROM Reviews rv JOIN @@ -54,20 +56,30 @@ def get_reviews_for_company(company_name): Companies c ON r.companyID = c.companyID WHERE c.name = %s - ''' - # get the database connection, execute the query, and + # Get the database connection, execute the query, and # fetch the results as a Python Dictionary cursor = db.get_db().cursor() cursor.execute(query, (company_name,)) # Passing company_name as a parameter theData = cursor.fetchall() + # Format the results into a structured dictionary + results = [ + { + "content": row["content"], + "roleName": row["roleName"], + "reviewType": row["reviewType"] + } + for row in theData + ] + # Make the response - response = make_response(jsonify(theData)) + response = make_response(jsonify(results)) response.status_code = 200 return response + # Get reviews for a specific company @searcher.route('/interviewReportsForCompany/', methods=['GET']) def get_interview_reports_for_company(company_name): diff --git a/app/src/Home.py b/app/src/Home.py index 61b08eb166..b500296da0 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -61,13 +61,13 @@ st.session_state['first_name'] = 'Riley' st.switch_page('pages/200_CoOp_Reviewer_Home.py') -if st.button('Act as System Administrator', +if st.button('Act as Alex Admin, System Administrator', type = 'primary', use_container_width=True): st.session_state['authenticated'] = True st.session_state['role'] = 'administrator' - st.session_state['first_name'] = 'SysAdmin' - logger.info("Logging in as System Administrator") + st.session_state['first_name'] = 'Alex' + logger.info("Logging in as Alex Admin, System Administrator") st.switch_page('pages/300_System_Administrator_Home.py') diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index ef240bd477..d97d78d489 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -28,6 +28,6 @@ if reviews: st.write("### Reviews for this Company:") # Display reviews in a table format - st.dataframe(reviews) + st.dataframe(reviews, use_container_width=True) else: st.write("No reviews available for this company.") \ No newline at end of file diff --git a/app/src/pages/1002_Interview_Information.py b/app/src/pages/1002_Interview_Information.py index 0fce324637..e0a780549a 100644 --- a/app/src/pages/1002_Interview_Information.py +++ b/app/src/pages/1002_Interview_Information.py @@ -28,6 +28,6 @@ if reviews: st.write("### Interview Feedback for this Company:") # Display reviews in a table format - st.dataframe(reviews) + st.dataframe(reviews, use_container_width=True) else: st.write("No interview feedback available for this company.") From ec974ec971120b603731869ce78512be03646bdc Mon Sep 17 00:00:00 2001 From: sevensrig Date: Fri, 6 Dec 2024 14:36:24 -0500 Subject: [PATCH 60/75] Got rid of duplicate skills in the skills dropdown --- app/src/pages/1003_Skill_Matching.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/pages/1003_Skill_Matching.py b/app/src/pages/1003_Skill_Matching.py index a22517c7c9..0ffdddb18c 100644 --- a/app/src/pages/1003_Skill_Matching.py +++ b/app/src/pages/1003_Skill_Matching.py @@ -17,13 +17,13 @@ skills = requests.get('http://api:4000/s/possibleSkills').json() -# Extract and split skillsRequired into a list of individual skills -skillsRequired = [] +# Extract and split skillsRequired into a set of unique skills +skillsRequired = set() for item in skills: # Split the skills by commas and strip any surrounding whitespace skills = item["skillsRequired"].split(",") - # Add each skill to the list - skillsRequired.extend([skill.strip() for skill in skills]) + # Add each skill to the set + skillsRequired.update(skill.strip() for skill in skills) # Display a dropdown menu with company names From b1f8c6a9bf7275fb7fdbe9314b150c36fa803ff2 Mon Sep 17 00:00:00 2001 From: diva-chhabra Date: Fri, 6 Dec 2024 16:53:45 -0500 Subject: [PATCH 61/75] Add files via upload --- app/src/pages/3101_Admin_Dashboard.py | 21 +++++++++++++ app/src/pages/3102_Content_Moderation.py | 28 +++++++++++++++++ app/src/pages/3103_Company_Role_Manager.py | 20 +++++++++++++ .../pages/3104_Feedback_Feature_Tracker.py | 22 ++++++++++++++ app/src/pages/3105_Analytics_Trends.py | 28 +++++++++++++++++ app/src/pages/400_Alex_Admin_Home.py | 30 +++++++++++++++++++ 6 files changed, 149 insertions(+) create mode 100644 app/src/pages/3101_Admin_Dashboard.py create mode 100644 app/src/pages/3102_Content_Moderation.py create mode 100644 app/src/pages/3103_Company_Role_Manager.py create mode 100644 app/src/pages/3104_Feedback_Feature_Tracker.py create mode 100644 app/src/pages/3105_Analytics_Trends.py create mode 100644 app/src/pages/400_Alex_Admin_Home.py diff --git a/app/src/pages/3101_Admin_Dashboard.py b/app/src/pages/3101_Admin_Dashboard.py new file mode 100644 index 0000000000..6ed35c76bc --- /dev/null +++ b/app/src/pages/3101_Admin_Dashboard.py @@ -0,0 +1,21 @@ +import streamlit as st + +def admin_dashboard(): + st.title("Admin Dashboard") + st.subheader("User Activity Metrics") + st.write("Metrics for platform engagement and activity (e.g., number of active users, reviews submitted).") + + st.subheader("Flagged Reviews") + st.write("List of reviews flagged by users or detected by the system for inappropriate content.") + st.table([["Review ID", "User", "Reason for Flagging", "Timestamp"], + [1, "User A", "Spam", "2024-12-06 10:00"], + [2, "User B", "Inappropriate Language", "2024-12-05 15:30"]]) + + st.subheader("New Submissions") + st.write("Monitor new content added by users, awaiting admin approval.") + st.table([["Submission ID", "Type", "Submitted By", "Date"], + [101, "Review", "User C", "2024-12-06"], + [102, "Interview", "User D", "2024-12-05"]]) + +# Display the screen +admin_dashboard() \ No newline at end of file diff --git a/app/src/pages/3102_Content_Moderation.py b/app/src/pages/3102_Content_Moderation.py new file mode 100644 index 0000000000..900bf20d28 --- /dev/null +++ b/app/src/pages/3102_Content_Moderation.py @@ -0,0 +1,28 @@ +import streamlit as st + +def content_moderation_panel(): + st.title("Content Moderation Panel") + st.subheader("Flagged Posts") + st.write("Review flagged posts and take appropriate action.") + st.table([["Post ID", "User", "Reason", "Date Flagged"], + [201, "User X", "Spam", "2024-12-06"], + [202, "User Y", "Hate Speech", "2024-12-05"]]) + + st.subheader("Moderation Actions") + st.write("Select a post to approve, edit, or remove.") + + selected_post = st.selectbox("Choose a post to moderate:", ["Post 201", "Post 202"]) + if st.button("Approve"): + st.success(f"Post {selected_post} approved.") + if st.button("Edit"): + st.info(f"Post {selected_post} marked for editing.") + if st.button("Remove"): + st.error(f"Post {selected_post} removed.") + + st.subheader("Moderation History") + st.write("View the history of actions taken on flagged posts.") + st.table([["Post ID", "Action Taken", "Moderator", "Date"], + [201, "Approved", "Admin A", "2024-12-06"]]) + +# Display the screen +content_moderation_panel() \ No newline at end of file diff --git a/app/src/pages/3103_Company_Role_Manager.py b/app/src/pages/3103_Company_Role_Manager.py new file mode 100644 index 0000000000..3ae9a6bfda --- /dev/null +++ b/app/src/pages/3103_Company_Role_Manager.py @@ -0,0 +1,20 @@ +import streamlit as st + +def company_role_manager(): + st.title("Company and Role Manager") + st.subheader("Edit Company Profiles") + st.write("Update information about companies and roles.") + + company = st.selectbox("Choose a company to update:", ["Company A", "Company B", "Company C"]) + st.text_area("Company Description", value="Edit the company's profile details here.") + if st.button("Save Changes"): + st.success(f"Profile for {company} updated.") + + st.subheader("Incomplete Data") + st.write("Companies with missing or outdated profiles:") + st.table([["Company", "Missing Details"], + ["Company D", "Contact Information"], + ["Company E", "Role Descriptions"]]) + +# Display the screen +company_role_manager() \ No newline at end of file diff --git a/app/src/pages/3104_Feedback_Feature_Tracker.py b/app/src/pages/3104_Feedback_Feature_Tracker.py new file mode 100644 index 0000000000..797731483b --- /dev/null +++ b/app/src/pages/3104_Feedback_Feature_Tracker.py @@ -0,0 +1,22 @@ +import streamlit as st + +def feedback_feature_tracker(): + st.title("Feedback and Feature Tracker") + st.subheader("User Feedback") + st.write("View and categorize user feedback.") + feedback = st.selectbox("Select feedback to review:", ["Feature Request A", "Bug Report B", "Improvement C"]) + if st.button("Mark as In Progress"): + st.info(f"Feedback '{feedback}' marked as in progress.") + if st.button("Mark as Implemented"): + st.success(f"Feedback '{feedback}' marked as implemented.") + if st.button("Reject"): + st.error(f"Feedback '{feedback}' rejected.") + + st.subheader("Feature Status") + st.write("Monitor the status of user-submitted features.") + st.table([["Feature", "Status", "Last Updated"], + ["Feature A", "In Progress", "2024-12-05"], + ["Feature B", "Implemented", "2024-12-04"]]) + +# Display the screen +feedback_feature_tracker() \ No newline at end of file diff --git a/app/src/pages/3105_Analytics_Trends.py b/app/src/pages/3105_Analytics_Trends.py new file mode 100644 index 0000000000..042b0a6c7b --- /dev/null +++ b/app/src/pages/3105_Analytics_Trends.py @@ -0,0 +1,28 @@ +import streamlit as st + +def analytics_trends_page(): + st.title("Analytics and Trends Page") + st.subheader("Trends in Reviews") + st.write("Visualize trends in student reviews, company searches, and engagement.") + + st.line_chart({ + "2024-12-01": [10, 15, 20], + "2024-12-02": [20, 25, 30], + "2024-12-03": [30, 35, 40] + }) + + st.subheader("Category Insights") + st.write("View insights by category or industry.") + st.bar_chart({ + "Industry A": [5, 10, 15], + "Industry B": [10, 20, 30], + "Industry C": [15, 25, 35] + }) + + st.subheader("Engagement Metrics") + st.write("Track user engagement metrics.") + st.metric(label="Active Users Today", value=100, delta=10) + st.metric(label="Reviews Submitted", value=50, delta=5) + +# Display the screen +analytics_trends_page() \ No newline at end of file diff --git a/app/src/pages/400_Alex_Admin_Home.py b/app/src/pages/400_Alex_Admin_Home.py new file mode 100644 index 0000000000..8cd15313f8 --- /dev/null +++ b/app/src/pages/400_Alex_Admin_Home.py @@ -0,0 +1,30 @@ +import streamlit as st +import logging + +logging.basicConfig(level=logging.INFO) + +def alex_admin_home(): + st.title("Welcome, Alex (Admin)") + st.write("Choose one of the following options to access admin functionalities:") + + if st.button("Go to Admin Dashboard", type="primary", use_container_width=True): + logging.info("Navigating to 3101_Admin_Dashboard") + st.switch_page('pages/3101_Admin_Dashboard.py') + + if st.button("Go to Content Moderation Panel", type="primary", use_container_width=True): + logging.info("Navigating to 3102_Content_Moderation") + st.switch_page('pages/3102_Content_Moderation.py') + + if st.button("Go to Company and Role Manager", type="primary", use_container_width=True): + logging.info("Navigating to 3103_Company_Role_Manager") + st.switch_page('pages/3103_Company_Role_Manager.py') + + if st.button("Go to Feedback and Feature Tracker", type="primary", use_container_width=True): + logging.info("Navigating to 3104_Feedback_Feature_Tracker") + st.switch_page('pages/3104_Feedback_Feature_Tracker.py') + + if st.button("Go to Analytics and Trends Page", type="primary", use_container_width=True): + logging.info("Navigating to 3105_Analytics_Trends") + st.switch_page('pages/3105_Analytics_Trends.py') + +alex_admin_home() \ No newline at end of file From 56430036ad1a4b4b59728499460d2db538ed912c Mon Sep 17 00:00:00 2001 From: sevensrig Date: Fri, 6 Dec 2024 17:31:25 -0500 Subject: [PATCH 62/75] Delete unnecessary files --- .../300_System_Administrator_Home copy.py | 40 ------------------- app/src/pages/3101_Admin_Dashboard.py | 21 ---------- app/src/pages/3102_Content_Moderation.py | 28 ------------- app/src/pages/3103_Company_Role_Manager.py | 20 ---------- .../pages/3104_Feedback_Feature_Tracker.py | 22 ---------- app/src/pages/3105_Analytics_Trends.py | 28 ------------- 6 files changed, 159 deletions(-) delete mode 100644 app/src/pages/300_System_Administrator_Home copy.py delete mode 100644 app/src/pages/3101_Admin_Dashboard.py delete mode 100644 app/src/pages/3102_Content_Moderation.py delete mode 100644 app/src/pages/3103_Company_Role_Manager.py delete mode 100644 app/src/pages/3104_Feedback_Feature_Tracker.py delete mode 100644 app/src/pages/3105_Analytics_Trends.py diff --git a/app/src/pages/300_System_Administrator_Home copy.py b/app/src/pages/300_System_Administrator_Home copy.py deleted file mode 100644 index b3c9d582b1..0000000000 --- a/app/src/pages/300_System_Administrator_Home copy.py +++ /dev/null @@ -1,40 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import streamlit as st -from modules.nav import SideBarLinks - -st.set_page_config(layout = 'wide') - -# Show appropriate sidebar links for the role of the currently logged in user -SideBarLinks() - -st.title(f"Welcome System Administrator, {st.session_state['first_name']}.") -st.write('') -st.write('') -st.write('### What would you like to do today?') - -if st.button('View Admin Dashboard', - type='primary', - use_container_width=True): - st.switch_page('pages/3001_Admin_Dashboard.py') - -if st.button('View and Moderate Flagged Posts', - type='primary', - use_container_width=True): - st.switch_page('pages/3002_Flagged_Posts.py') - -if st.button('Edit and Update Company Profiles', - type='primary', - use_container_width=True): - st.switch_page('pages/3003_Company_Profiles.py') - -if st.button('View and Categorize User Feedback', - type='primary', - use_container_width=True): - st.switch_page('pages/3004_User_Feedback.py') - -if st.button('View Analytics and Trends', - type='primary', - use_container_width=True): - st.switch_page('pages/3005_Analytics_and_Trends.py') - diff --git a/app/src/pages/3101_Admin_Dashboard.py b/app/src/pages/3101_Admin_Dashboard.py deleted file mode 100644 index 6ed35c76bc..0000000000 --- a/app/src/pages/3101_Admin_Dashboard.py +++ /dev/null @@ -1,21 +0,0 @@ -import streamlit as st - -def admin_dashboard(): - st.title("Admin Dashboard") - st.subheader("User Activity Metrics") - st.write("Metrics for platform engagement and activity (e.g., number of active users, reviews submitted).") - - st.subheader("Flagged Reviews") - st.write("List of reviews flagged by users or detected by the system for inappropriate content.") - st.table([["Review ID", "User", "Reason for Flagging", "Timestamp"], - [1, "User A", "Spam", "2024-12-06 10:00"], - [2, "User B", "Inappropriate Language", "2024-12-05 15:30"]]) - - st.subheader("New Submissions") - st.write("Monitor new content added by users, awaiting admin approval.") - st.table([["Submission ID", "Type", "Submitted By", "Date"], - [101, "Review", "User C", "2024-12-06"], - [102, "Interview", "User D", "2024-12-05"]]) - -# Display the screen -admin_dashboard() \ No newline at end of file diff --git a/app/src/pages/3102_Content_Moderation.py b/app/src/pages/3102_Content_Moderation.py deleted file mode 100644 index 900bf20d28..0000000000 --- a/app/src/pages/3102_Content_Moderation.py +++ /dev/null @@ -1,28 +0,0 @@ -import streamlit as st - -def content_moderation_panel(): - st.title("Content Moderation Panel") - st.subheader("Flagged Posts") - st.write("Review flagged posts and take appropriate action.") - st.table([["Post ID", "User", "Reason", "Date Flagged"], - [201, "User X", "Spam", "2024-12-06"], - [202, "User Y", "Hate Speech", "2024-12-05"]]) - - st.subheader("Moderation Actions") - st.write("Select a post to approve, edit, or remove.") - - selected_post = st.selectbox("Choose a post to moderate:", ["Post 201", "Post 202"]) - if st.button("Approve"): - st.success(f"Post {selected_post} approved.") - if st.button("Edit"): - st.info(f"Post {selected_post} marked for editing.") - if st.button("Remove"): - st.error(f"Post {selected_post} removed.") - - st.subheader("Moderation History") - st.write("View the history of actions taken on flagged posts.") - st.table([["Post ID", "Action Taken", "Moderator", "Date"], - [201, "Approved", "Admin A", "2024-12-06"]]) - -# Display the screen -content_moderation_panel() \ No newline at end of file diff --git a/app/src/pages/3103_Company_Role_Manager.py b/app/src/pages/3103_Company_Role_Manager.py deleted file mode 100644 index 3ae9a6bfda..0000000000 --- a/app/src/pages/3103_Company_Role_Manager.py +++ /dev/null @@ -1,20 +0,0 @@ -import streamlit as st - -def company_role_manager(): - st.title("Company and Role Manager") - st.subheader("Edit Company Profiles") - st.write("Update information about companies and roles.") - - company = st.selectbox("Choose a company to update:", ["Company A", "Company B", "Company C"]) - st.text_area("Company Description", value="Edit the company's profile details here.") - if st.button("Save Changes"): - st.success(f"Profile for {company} updated.") - - st.subheader("Incomplete Data") - st.write("Companies with missing or outdated profiles:") - st.table([["Company", "Missing Details"], - ["Company D", "Contact Information"], - ["Company E", "Role Descriptions"]]) - -# Display the screen -company_role_manager() \ No newline at end of file diff --git a/app/src/pages/3104_Feedback_Feature_Tracker.py b/app/src/pages/3104_Feedback_Feature_Tracker.py deleted file mode 100644 index 797731483b..0000000000 --- a/app/src/pages/3104_Feedback_Feature_Tracker.py +++ /dev/null @@ -1,22 +0,0 @@ -import streamlit as st - -def feedback_feature_tracker(): - st.title("Feedback and Feature Tracker") - st.subheader("User Feedback") - st.write("View and categorize user feedback.") - feedback = st.selectbox("Select feedback to review:", ["Feature Request A", "Bug Report B", "Improvement C"]) - if st.button("Mark as In Progress"): - st.info(f"Feedback '{feedback}' marked as in progress.") - if st.button("Mark as Implemented"): - st.success(f"Feedback '{feedback}' marked as implemented.") - if st.button("Reject"): - st.error(f"Feedback '{feedback}' rejected.") - - st.subheader("Feature Status") - st.write("Monitor the status of user-submitted features.") - st.table([["Feature", "Status", "Last Updated"], - ["Feature A", "In Progress", "2024-12-05"], - ["Feature B", "Implemented", "2024-12-04"]]) - -# Display the screen -feedback_feature_tracker() \ No newline at end of file diff --git a/app/src/pages/3105_Analytics_Trends.py b/app/src/pages/3105_Analytics_Trends.py deleted file mode 100644 index 042b0a6c7b..0000000000 --- a/app/src/pages/3105_Analytics_Trends.py +++ /dev/null @@ -1,28 +0,0 @@ -import streamlit as st - -def analytics_trends_page(): - st.title("Analytics and Trends Page") - st.subheader("Trends in Reviews") - st.write("Visualize trends in student reviews, company searches, and engagement.") - - st.line_chart({ - "2024-12-01": [10, 15, 20], - "2024-12-02": [20, 25, 30], - "2024-12-03": [30, 35, 40] - }) - - st.subheader("Category Insights") - st.write("View insights by category or industry.") - st.bar_chart({ - "Industry A": [5, 10, 15], - "Industry B": [10, 20, 30], - "Industry C": [15, 25, 35] - }) - - st.subheader("Engagement Metrics") - st.write("Track user engagement metrics.") - st.metric(label="Active Users Today", value=100, delta=10) - st.metric(label="Reviews Submitted", value=50, delta=5) - -# Display the screen -analytics_trends_page() \ No newline at end of file From 771433ace414fa316c47e955b8026fa4923902d3 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Fri, 6 Dec 2024 17:48:19 -0500 Subject: [PATCH 63/75] Added annalise pages --- app/src/Home.py | 6 +- app/src/modules/nav.py | 8 ++ app/src/pages/20_Admin_Home.py | 17 ----- ...s.py => 3005_Analytics_and_Trends copy.py} | 0 app/src/pages/4001_Analytics_Page.py | 75 +++++++++++++++++++ app/src/pages/4002_Feedback_Data.py | 75 +++++++++++++++++++ app/src/pages/400_Analyst_Home.py | 26 +++++++ 7 files changed, 187 insertions(+), 20 deletions(-) delete mode 100644 app/src/pages/20_Admin_Home.py rename app/src/pages/{3005_Analytics_and_Trends.py => 3005_Analytics_and_Trends copy.py} (100%) create mode 100644 app/src/pages/4001_Analytics_Page.py create mode 100644 app/src/pages/4002_Feedback_Data.py create mode 100644 app/src/pages/400_Analyst_Home.py diff --git a/app/src/Home.py b/app/src/Home.py index 61f9ef4d61..06521aa7c5 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -77,7 +77,7 @@ type = 'primary', use_container_width=True): st.session_state['authenticated'] = True - st.session_state['role'] = 'administrator' - st.session_state['first_name'] = 'SysAdmin' - st.switch_page('pages/20_Admin_Home.py') + st.session_state['role'] = 'analyst' + st.session_state['first_name'] = 'Annalise' + st.switch_page('pages/400_Analyst_Home.py') diff --git a/app/src/modules/nav.py b/app/src/modules/nav.py index 8090d2698d..8c5ace0a8c 100644 --- a/app/src/modules/nav.py +++ b/app/src/modules/nav.py @@ -62,6 +62,11 @@ def ReviewerPageNav(): def AdminPageNav(): st.sidebar.page_link("pages/300_System_Administrator_Home.py", label="System Admin", icon="🖥️") + #### ------------------------ System Admin Role ------------------------ +def AnalyistPageNav(): + st.sidebar.page_link("pages/400_Analyst_Home.py", label="Site Analyst", icon="📊") + + # --------------------------------Links Function ----------------------------------------------- def SideBarLinks(show_home=False): @@ -102,6 +107,9 @@ def SideBarLinks(show_home=False): if st.session_state["role"] == "administrator": AdminPageNav() + if st.session_state["role"] == "analyst": + AnalyistPageNav() + # Always show the About page at the bottom of the list of links AboutPageNav() diff --git a/app/src/pages/20_Admin_Home.py b/app/src/pages/20_Admin_Home.py deleted file mode 100644 index 0dbd0f36b4..0000000000 --- a/app/src/pages/20_Admin_Home.py +++ /dev/null @@ -1,17 +0,0 @@ -import logging -logger = logging.getLogger(__name__) - -import streamlit as st -from modules.nav import SideBarLinks -import requests - -st.set_page_config(layout = 'wide') - -SideBarLinks() - -st.title('System Admin Home Page') - -if st.button('Update ML Models', - type='primary', - use_container_width=True): - st.switch_page('pages/21_ML_Model_Mgmt.py') \ No newline at end of file diff --git a/app/src/pages/3005_Analytics_and_Trends.py b/app/src/pages/3005_Analytics_and_Trends copy.py similarity index 100% rename from app/src/pages/3005_Analytics_and_Trends.py rename to app/src/pages/3005_Analytics_and_Trends copy.py diff --git a/app/src/pages/4001_Analytics_Page.py b/app/src/pages/4001_Analytics_Page.py new file mode 100644 index 0000000000..411e9b5a7f --- /dev/null +++ b/app/src/pages/4001_Analytics_Page.py @@ -0,0 +1,75 @@ +import logging +logger = logging.getLogger(__name__) +import requests +import pandas as pd +import streamlit as st +from streamlit_extras.app_logo import add_logo +import matplotlib.pyplot as plt + +# Safe initialization of session state variables +if "first_name" not in st.session_state: + st.session_state.first_name = "Guest" + +# Call the SideBarLinks from the nav module +from modules.nav import SideBarLinks +SideBarLinks() + +# Set the header of the page +st.header('View Analytics and Trends') +st.write(f"### Hi, {st.session_state['first_name']}.") + +# Fetch industries +industries = [] +try: + industries = requests.get("http://api:4000/c/industries").json() +except Exception as e: + st.write(f"Error: {e}") + st.write("Could not connect to database to get industries.") +if "industries" not in st.session_state: + st.session_state.industries = pd.DataFrame(industries) + +# Fetch reviews +reviews = [] +try: + reviews = requests.get("http://api:4000/c/reviews").json() +except Exception as e: + st.write(f"Error: {e}") + st.write("Could not connect to database to get reviews.") +if "reviews" not in st.session_state: + st.session_state.reviews = pd.DataFrame(reviews) + +# Title +st.title("Trends in Student Reviews and Companies") +st.subheader("Trend Data") + +# Plot trends if data is valid +if not st.session_state.industries.empty and not st.session_state.reviews.empty: + fig, ax = plt.subplots(figsize=(10, 6)) + ax.plot(st.session_state.reviews["Industry"], st.session_state.reviews['NumReviews'], label="reviews", marker="o") + ax.plot(st.session_state.industries["Industry"], st.session_state.industries['NumCompany'], label="Companies", marker="o") + ax.set_ylabel("Count") + ax.set_title("Trends by Category") + ax.set_xticklabels(st.session_state.industries["Industry"], rotation=45, ha="right") + ax.legend() + ax.grid(True) + st.pyplot(fig) +else: + st.write("Insufficient data to display trends.") + +# Actionable Insights +st.subheader("Actionable Insights") +if not st.session_state.industries.empty: + most_companies = st.session_state.industries.sort_values("NumCompany").iloc[-1] + st.write(f"**Industry with Most Companies**: {most_companies['Industry']} ({most_companies['NumCompany']} companies)") + +if not st.session_state.reviews.empty: + most_reviews = st.session_state.reviews.sort_values("NumReviews").iloc[-1] + st.write(f"**Industry with Most Reviews**: {most_reviews['Industry']} ({most_reviews['NumReviews']} reviews)") + +# Display Data Table +if "Industry" in st.session_state.industries and "Industry" in st.session_state.reviews: + df = pd.merge(st.session_state.industries, st.session_state.reviews, on="Industry") + st.subheader("Data Table") + st.dataframe(df) +else: + st.write("Data table cannot be displayed due to missing columns.") diff --git a/app/src/pages/4002_Feedback_Data.py b/app/src/pages/4002_Feedback_Data.py new file mode 100644 index 0000000000..a893441b19 --- /dev/null +++ b/app/src/pages/4002_Feedback_Data.py @@ -0,0 +1,75 @@ +import logging +logger = logging.getLogger(__name__) +import pandas as pd +import requests +import streamlit as st +from streamlit_extras.app_logo import add_logo +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px +from modules.nav import SideBarLinks + +# Call the SideBarLinks from the nav module in the modules directory +SideBarLinks() + +# set the header of the page +st.header('View and Categorize User Feedback') + +# You can access the session state to make a more customized/personalized app experience +st.write(f"### Hi, {st.session_state['first_name']}.") + +# get the feedbacks +try: + feedback = requests.get("http://api:4000/f/feedback").json() +except: + st.write("Could not to conncet to database to get user feedback") + +if "feedback_df" not in st.session_state: + st.session_state.feedback_df = pd.DataFrame(feedback) + +# title +st.title("User Feedback Management Interface") + +# Sort by status +st.subheader("Filter or Sort Feedback") +filter_option = st.radio( + "Select Filter or Sort Option", + ["Default", "Show Only In Progress", "Show Only Implemented", "Show Only Rejected", "Sort by FeedbackID"], + index=0, +) + +# Apply sorting or filtering +filtered_feedback_df = st.session_state.feedback_df.copy() + +if filter_option == "Show Only In Progress": + filtered_feedback_df = filtered_feedback_df[ + filtered_feedback_df["status"] == "In Progress" + ] +elif filter_option == "Show Only Implemented": + filtered_feedback_df = filtered_feedback_df[ + filtered_feedback_df["status"] == "Implemented" + ] +elif filter_option == "Show Only Rejected": + filtered_feedback_df = filtered_feedback_df[ + filtered_feedback_df["status"] == "Rejected" + ] +elif filter_option == "Sort by FeedbackID": + filtered_feedback_df = filtered_feedback_df.sort_values('feedbackID') + +else: + filtered_feedback_df["status"] = pd.Categorical( + filtered_feedback_df["status"], + categories=["In Progress", "Implemented", "Rejected"], + ordered=True, + ) + filtered_feedback_df = filtered_feedback_df.sort_values("status") + +# Select and rearrange columns +display_columns = ["status", "feedbackID", "userID", "timestamp", "header", "content"] +filtered_feedback_df = filtered_feedback_df[display_columns] + +filtered_feedback_df = filtered_feedback_df.reset_index(drop=True) + +# Display feedback table without index +st.subheader("Feedback List") +st.dataframe(filtered_feedback_df) diff --git a/app/src/pages/400_Analyst_Home.py b/app/src/pages/400_Analyst_Home.py new file mode 100644 index 0000000000..b976976914 --- /dev/null +++ b/app/src/pages/400_Analyst_Home.py @@ -0,0 +1,26 @@ +import logging +logger = logging.getLogger(__name__) +import streamlit as st +from modules.nav import SideBarLinks + +st.set_page_config(layout = 'wide') + +# Show appropriate sidebar links for the role of the currently logged in user +SideBarLinks() + +st.title(f"Welcome Analyst, {st.session_state['first_name']}.") +st.write('') +st.write('') +st.write('### What would you like to do today?') + + +if st.button('View Analytics and Trends', + type='primary', + use_container_width=True): + st.switch_page('pages/4001_Analytics_Page.py') + +if st.button('View Feedback Data', + type='primary', + use_container_width=True): + st.switch_page('pages/4002_Feedback_Data.py') + From de8487f9ac9260bd264dbb4be1153d9b369bd886 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Fri, 6 Dec 2024 18:14:48 -0500 Subject: [PATCH 64/75] Updated readme --- README.md | 117 +++++++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 94291428ad..4bc58f3c47 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,87 @@ -# Fall 2024 CS 3200 Project Template Repository +# COUPE: TRACE for Co-Ops -This repo is a template for your semester project. It includes most of the infrastructure setup (containers) and sample code and data throughout. Explore it fully and ask questions. +COUPE is a data-driven platform designed to revolutionize the co-op search process for Northeastern University students by offering peer-to-peer insights into company experiences. Our mission is to provide students with transparent, verified, and meaningful reviews on workplace culture, roles, and interview processes to help them find their ideal co-op match. -## Prerequisites +## Key Features +- **Peer-Reviewed Insights** + Access authentic reviews about company culture, roles, and work-life balance written by fellow students. +- **Application and Interview Guidance** + Gain detailed insights into application processes, interview questions, and preparation tips. +- **Incentivized Contribution System** + Share your own co-op experiences to unlock access to additional content and earn platform rewards. -- A GitHub Account -- A terminal-based or GUI git client -- VSCode with the Python Plugin -- A distrobution of Python running on your laptop (Choco (for Windows), brew (for Macs), miniconda, Anaconda, etc). +--- -## Current Project Components +## Target Users +### **Persona 1: Sebastian Studentson** +A second-year CS student seeking guidance for his first co-op, overwhelmed by options and in need of peer insights to confidently navigate his search. -Currently, there are three major components which will each run in their own Docker Containers: +### **Persona 2: Riley Reviewer** +A fourth-year marketing major who wants to share detailed feedback on their co-op experience to help others make informed decisions. -- Streamlit App in the `./app` directory -- Flask REST api in the `./api` directory -- SQL files for your data model and data base in the `./database-files` directory +### **Persona 3: Alex Admin** +The platform administrator responsible for moderating reviews, resolving disputes, and maintaining the integrity of the platform. -## Suggestion for Learning the Project Code Base +### **Persona 4: Annalise Analyst** +A data analyst evaluating user trends and engagement to drive improvements in platform features and user experience. -If you are not familiar with web app development, this code base might be confusing. You will probably want two versions though: -1. One version for you to explore, try things, break things, etc. We'll call this your **Personal Repo** -1. One version of the repo that your team will share. We'll call this the **Team Repo**. +--- +## Technology Stack +- **Frontend:** Streamlit +- **Middleware:** Python Flask +- **Backend:** MySQL +- **Containerization:** Docker +- **Development Tools:** VSCode, DataGrip -### Setting Up Your Personal Repo +--- -1. In GitHub, click the **fork** button in the upper right corner of the repo screen. -1. When prompted, give the new repo a unique name, perhaps including your last name and the word 'personal'. -1. Once the fork has been created, clone YOUR forked version of the repo to your computer. -1. Set up the `.env` file in the `api` folder based on the `.env.template` file. -1. Start the docker containers. +## Database Schema +The database consists of multiple interconnected tables, including: +- **User:** Stores user information, including roles (e.g., Admin, Analyst). +- **Companies:** Lists companies with associated industries and locations. +- **Role:** Details job roles, required skills, and associated companies. +- **Reviews:** Houses peer reviews with fields for headings, content, and engagement metrics. +- **Comments:** Allows threaded discussions on reviews. +- **Badges:** Tracks user achievements and contributions. -### Setting Up Your Team Repo +For a complete SQL DDL script, refer to [schema.sql](#). -Before you start: As a team, one person needs to assume the role of *Team Project Repo Owner*. +--- -1. The Team Project Repo Owner needs to fork this template repo into their own GitHub account **and give the repo a name consistent with your project's name**. If you're worried that the repo is public, don't. Every team is doing a different project. -1. In the newly forked team repo, the Team Project Repo Owner should go to the **Settings** tab, choose **Collaborators and Teams** on the left-side panel. Add each of your team members to the repository with Write access. -1. Each of the other team members will receive an invitation to join. Obviously accept the invite. -1. Once that process is complete, each team member, including the repo owner, should clone the Team's Repo to their local machines (in a different location than your Personal Project Repo). +## REST API Endpoints +Here is an example of the REST API matrix. For detailed documentation, refer to the `API_DOCS.md` in this repository. -## Controlling the Containers +| Resource | GET | POST | PUT | DELETE | +|----------------------|-------------------------------------------|-------------------------------|---------------------|-------------------| +| `/companiesWithReviews` | Return all companies with reviews. | N/A | N/A | N/A | +| `/reviews` | Retrieve reviews based on filters. | Submit a new review. | Update an existing review. | Delete a review. | +| `/admin/flaggedContent` | Retrieve flagged reviews for moderation. | N/A | Resolve flagged content. | Remove flagged content. | -- `docker compose up -d` to start all the containers in the background -- `docker compose down` to shutdown and delete the containers -- `docker compose up db -d` only start the database container (replace db with the other services as needed) -- `docker compose stop` to "turn off" the containers but not delete them. +--- +## ✨ User Stories +### Sebastian Studentson +- As a co-op searcher, I want to find detailed insights about a company’s culture and values to ensure alignment with my work style. -## Handling User Role Access and Control +### Riley Reviewer +- As a former co-op student, I want an easy-to-use feedback submission form to share structured and meaningful reviews. -In most applications, when a user logs in, they assume a particular role. For instance, when one logs in to a stock price prediction app, they may be a single investor, a portfolio manager, or a corporate executive (of a publicly traded company). Each of those *roles* will likely present some similar features as well as some different features when compared to the other roles. So, how do you accomplish this in Streamlit? This is sometimes called Role-based Access Control, or **RBAC** for short. +### Alex Admin +- As an admin, I need to moderate flagged reviews efficiently to maintain the platform's integrity. -The code in this project demonstrates how to implement a simple RBAC system in Streamlit but without actually using user authentication (usernames and passwords). The Streamlit pages from the original template repo are split up among 3 roles - Political Strategist, USAID Worker, and a System Administrator role (this is used for any sort of system tasks such as re-training ML model, etc.). It also demonstrates how to deploy an ML model. +### Annalise Analyst +- As an analyst, I need tools to identify gaps in content, such as underrepresented industries, and track user engagement. -Wrapping your head around this will take a little time and exploration of this code base. Some highlights are below. +--- -### Getting Started with the RBAC -1. We need to turn off the standard panel of links on the left side of the Streamlit app. This is done through the `app/src/.streamlit/config.toml` file. So check that out. We are turning it off so we can control directly what links are shown. -1. Then I created a new python module in `app/src/modules/nav.py`. When you look at the file, you will se that there are functions for basically each page of the application. The `st.sidebar.page_link(...)` adds a single link to the sidebar. We have a separate function for each page so that we can organize the links/pages by role. -1. Next, check out the `app/src/Home.py` file. Notice that there are 3 buttons added to the page and when one is clicked, it redirects via `st.switch_page(...)` to that Roles Home page in `app/src/pages`. But before the redirect, I set a few different variables in the Streamlit `session_state` object to track role, first name of the user, and that the user is now authenticated. -1. Notice near the top of `app/src/Home.py` and all other pages, there is a call to `SideBarLinks(...)` from the `app/src/nav.py` module. This is the function that will use the role set in `session_state` to determine what links to show the user in the sidebar. -1. The pages are organized by Role. Pages that start with a `0` are related to the *Political Strategist* role. Pages that start with a `1` are related to the *USAID worker* role. And, pages that start with a `2` are related to The *System Administrator* role. +## Wireframes +Wireframes for primary features, including the company culture overview and feedback submission forms, can be found in the `wireframes` directory. +--- -## Deploying An ML Model (Totally Optional for CS3200 Project) - -*Note*: This project only contains the infrastructure for a hypothetical ML model. - -1. Build, train, and test your ML model in a Jupyter Notebook. -1. Once you're happy with the model's performance, convert your Jupyter Notebook code for the ML model to a pure python script. You can include the `training` and `testing` functionality as well as the `prediction` functionality. You may or may not need to include data cleaning, though. -1. Check out the `api/backend/ml_models` module. In this folder, I've put a sample (read *fake*) ML model in `model01.py`. The `predict` function will be called by the Flask REST API to perform '*real-time*' prediction based on model parameter values that are stored in the database. **Important**: you would never want to hard code the model parameter weights directly in the prediction function. tl;dr - take some time to look over the code in `model01.py`. -1. The prediction route for the REST API is in `api/backend/customers/customer_routes.py`. Basically, it accepts two URL parameters and passes them to the `prediction` function in the `ml_models` module. The `prediction` route/function packages up the value(s) it receives from the model's `predict` function and send its back to Streamlit as JSON. -1. Back in streamlit, check out `app/src/pages/11_Prediction.py`. Here, I create two numeric input fields. When the button is pressed, it makes a request to the REST API URL `/c/prediction/.../...` function and passes the values from the two inputs as URL parameters. It gets back the results from the route and displays them. Nothing fancy here. - - +## How to Run Locally +1. Clone this repository: + ```bash + git clone https://github.com/zootsuitproductions/coupe.git + cd coupe From 594f2975234d40ce74b57e943a54ada95fdfda70 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Fri, 6 Dec 2024 18:23:57 -0500 Subject: [PATCH 65/75] Sebastian page view is a lot cleaner and can post comments. --- api/backend/coop_searcher/searcher_routes.py | 16 ++- api/backend/reviews/reviews_routes.py | 37 ++++++ .../pages/1001_Company_Position_Reviews.py | 109 +++++++++++++++--- app/src/pages/2002_My_Reviews.py | 37 ++++++ 4 files changed, 181 insertions(+), 18 deletions(-) diff --git a/api/backend/coop_searcher/searcher_routes.py b/api/backend/coop_searcher/searcher_routes.py index 76aecc076e..fcb7532d1c 100644 --- a/api/backend/coop_searcher/searcher_routes.py +++ b/api/backend/coop_searcher/searcher_routes.py @@ -46,7 +46,14 @@ def get_reviews_for_company(company_name): query = ''' SELECT rv.content, + rv.publishedAt, + rv.userID, + rv.reviewID, + rv.views, + rv.likes, + rv.heading, r.roleName, + r.roleID, rv.reviewType FROM Reviews rv @@ -68,8 +75,15 @@ def get_reviews_for_company(company_name): results = [ { "content": row["content"], + "heading": row["heading"], "roleName": row["roleName"], - "reviewType": row["reviewType"] + "reviewID": row["reviewID"], + "likes": row["likes"], + "views": row["views"], + "roleID": row["roleID"], + "publishedAt": row["publishedAt"], + "reviewType": row["reviewType"], + "userID": row["userID"] } for row in theData ] diff --git a/api/backend/reviews/reviews_routes.py b/api/backend/reviews/reviews_routes.py index 10a724db5d..93c973dff6 100644 --- a/api/backend/reviews/reviews_routes.py +++ b/api/backend/reviews/reviews_routes.py @@ -225,6 +225,43 @@ def add_review(): print(traceback.format_exc()) return jsonify({"error": error_message}), 500 + +# Assuming `reviews` is your Blueprint for this module +@reviews.route('/addComment', methods=['POST']) +def add_comment(): + comment_data = request.json + try: + # Get current timestamp for createdAt + current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + # Construct SQL query to insert the comment + query = """ + INSERT INTO Comments (reviewID, userID, content, createdAt, likes) + VALUES (%s, %s, %s, %s, %s) + """ + values = ( + comment_data["reviewID"], # Review ID to link the comment to + comment_data["userID"], # User ID of the commenter + comment_data["content"], # The comment text + current_time, # Use the current timestamp for createdAt + 0 # Default likes to 0 + ) + + # Execute the query + cursor = db.get_db().cursor() + cursor.execute(query, values) + db.get_db().commit() + + # Return success response + return jsonify({"message": "Comment added successfully!"}), 201 + + except Exception as e: + # Handle errors and return an error response + error_message = str(e) + print("Error:", error_message) + print(traceback.format_exc()) + return jsonify({"error": error_message}), 500 + # ------------------------------------------------------------ # get product information about a specific product # notice that the route takes and then you see id diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index d97d78d489..412af6e26b 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -1,33 +1,108 @@ import logging -logger = logging.getLogger(__name__) +import requests import streamlit as st from modules.nav import SideBarLinks -import requests + +# Set up logger +logger = logging.getLogger(__name__) # Call the SideBarLinks from the nav module in the modules directory SideBarLinks() -# set the header of the page +# Set the header of the page st.header('Find Company and Position Reviews') -# You can access the session state to make a more customized/personalized app experience +# Access the session state for personalization st.write(f"### Hi, {st.session_state['first_name']}.") -results = requests.get('http://api:4000/s/companiesWithReviews').json() +# Function to add a comment to a review +def add_comment(review_id, user_id, content): + try: + response = requests.post( + f"http://api:4000/r/addComment", + json={ + "reviewID": review_id, + "userID": user_id, + "content": content, + }, + ) + response.raise_for_status() + return response.json() # Assuming the API returns the created comment or success message + except requests.exceptions.RequestException as e: + logger.error(f"Failed to add comment to review {review_id}: {e}") + return None + +# Fetch companies with reviews +try: + results = requests.get('http://api:4000/s/companiesWithReviews').json() + company_names = [item["CompanyName"] for item in results] +except Exception as e: + st.error("Failed to fetch company data. Please try again later.") + logger.error(f"Error fetching companies: {e}") + company_names = [] + +# Dropdown for selecting a company +if company_names: + selected_company = st.selectbox("Select a Company:", company_names) + + if selected_company: + # Fetch reviews for the selected company + try: + reviews = requests.get(f'http://api:4000/s/reviewsForCompany/{selected_company}').json() + except Exception as e: + st.error("Failed to fetch reviews. Please try again later.") + logger.error(f"Error fetching reviews: {e}") + reviews = [] + + # Display reviews + if reviews: + st.write("### Reviews for this Company:") + + for review in reviews: + st.subheader(f"Review by User {review['userID']}") + st.write(f"**Role ID:** {review['roleID']}") + st.write(f"**Published At:** {review['publishedAt']}") + st.write(f"**Heading:** {review['heading']}") + st.write(f"**Content:** {review['content']}") + st.write(f"**Views:** {review['views']} | **Likes:** {review['likes']}") + st.write("---") -# Extract company names into a list -company_names = [item["CompanyName"] for item in results] + # Fetch comments for the current review + try: + comments = requests.get(f"http://api:4000/r/commentsByReview/{review['reviewID']}").json() + except Exception as e: + st.error("Failed to fetch comments. Please try again later.") + logger.error(f"Error fetching comments: {e}") + comments = [] -# Display a dropdown menu with company names -selected_company = st.selectbox("Select a Company:", company_names) + # Display comments + if comments: + st.write("#### Comments:") + for comment in comments: + st.write(f"- **User {comment['userID']}**: {comment['content']} (Likes: {comment['likes']})") + else: + st.write("No comments yet for this review.") -# Fetch the reviews for the selected company by company name -reviews = requests.get(f'http://api:4000/s/reviewsForCompany/{selected_company}').json() + # Add a form to post a new comment + with st.form(key=f"add_comment_form_{review['reviewID']}"): + st.subheader("Add a Comment") + new_comment_content = st.text_area("Your Comment", key=f"comment_content_{review['reviewID']}") + submit_comment_button = st.form_submit_button(label="Post Comment") -# Display the reviews if available -if reviews: - st.write("### Reviews for this Company:") - # Display reviews in a table format - st.dataframe(reviews, use_container_width=True) + if submit_comment_button and new_comment_content: + user_id = st.session_state.get("id") # Assuming user ID is stored in session state + comment_response = add_comment(review['reviewID'], user_id, new_comment_content) + if comment_response: + st.success("Comment added successfully!") + # Optionally refresh comments + comments.append({ + "userID": user_id, + "content": new_comment_content, + "likes": 0, + }) + else: + st.error("Failed to post comment. Please try again.") + else: + st.write("No reviews available for this company.") else: - st.write("No reviews available for this company.") \ No newline at end of file + st.write("No companies available to select.") diff --git a/app/src/pages/2002_My_Reviews.py b/app/src/pages/2002_My_Reviews.py index 0b8170ce51..b1de27f46a 100644 --- a/app/src/pages/2002_My_Reviews.py +++ b/app/src/pages/2002_My_Reviews.py @@ -45,6 +45,23 @@ def fetch_comments(review_id): logger.error(f"Failed to fetch comments for review {review_id}: {e}") return [] +# Function to add a comment to a review +def add_comment(review_id, user_id, content): + try: + response = requests.post( + f"http://api:4000/r/addComment", + json={ + "reviewID": review_id, + "userID": user_id, + "content": content, + }, + ) + response.raise_for_status() + return response.json() # Assuming the API returns the created comment or success message + except requests.exceptions.RequestException as e: + logger.error(f"Failed to add comment to review {review_id}: {e}") + return None + # If there are reviews, display them # Display the edit form for the currently selected review if "editing_review_id" not in st.session_state: @@ -75,6 +92,26 @@ def fetch_comments(review_id): st.markdown("*No comments yet.*") + # Add a form to post a new comment + with st.form(key=f"add_comment_form_{review['reviewID']}"): + st.subheader("Add a Comment") + new_comment_content = st.text_area("Your Comment", key=f"comment_content_{review['reviewID']}") + submit_comment_button = st.form_submit_button(label="Post Comment") + + if submit_comment_button and new_comment_content: + user_id = st.session_state.get("id") # Assuming user ID is stored in session state + comment_response = add_comment(review['reviewID'], user_id, new_comment_content) + if comment_response: + st.success("Comment added successfully!") + # Optionally refresh comments + comments.append({ + "userID": user_id, + "content": new_comment_content, + "likes": 0, + }) + else: + st.error("Failed to post comment. Please try again.") + # Display the edit button edit_button = st.button( From 2d13a84a2d86e50c60202e57bc6ddf536eae2f19 Mon Sep 17 00:00:00 2001 From: sevensrig Date: Fri, 6 Dec 2024 21:33:11 -0500 Subject: [PATCH 66/75] Added a button to flag reviews and a route corresponding --- api/backend/coop_searcher/searcher_routes.py | 58 +++++++++++++++++++ .../pages/1001_Company_Position_Reviews.py | 37 ++++++++++++ 2 files changed, 95 insertions(+) diff --git a/api/backend/coop_searcher/searcher_routes.py b/api/backend/coop_searcher/searcher_routes.py index fcb7532d1c..3a3c8a1ec5 100644 --- a/api/backend/coop_searcher/searcher_routes.py +++ b/api/backend/coop_searcher/searcher_routes.py @@ -174,3 +174,61 @@ def get_roles_for_skill(skill): # Log the error and return a 500 error response current_app.logger.error(f"Error fetching roles for skill {skill}: {e}") return make_response(jsonify({"error": "Database query failed"}), 500) + + +# Increment likes for a specific review +@searcher.route('/review//like', methods=['POST']) +def like_review(review_id): + try: + # Query to increment the likes for the given review ID + query = ''' + UPDATE Reviews + SET likes = likes + 1 + WHERE reviewID = %s; + ''' + + # Get the database connection and execute the query + cursor = db.get_db().cursor() + cursor.execute(query, (review_id,)) + db.get_db().commit() + + # Check if any row was updated + if cursor.rowcount == 0: + return make_response(jsonify({"message": "Review not found"}), 404) + + # Return a success response + return make_response(jsonify({"message": "Review liked successfully!"}), 200) + + except Exception as e: + # Log the error and return a 500 error response + current_app.logger.error(f"Error liking review with ID {review_id}: {e}") + return make_response(jsonify({"error": "Database query failed"}), 500) + + +# Flag a review +@searcher.route('/review//flag', methods=['POST']) +def flag_review(review_id): + try: + # Query to flag the review + query = ''' + UPDATE Reviews + SET isFlagged = TRUE + WHERE reviewID = %s; + ''' + + # Get the database connection and execute the query + cursor = db.get_db().cursor() + cursor.execute(query, (review_id,)) + db.get_db().commit() + + # Check if any row was updated + if cursor.rowcount == 0: + return make_response(jsonify({"message": "Review not found"}), 404) + + # Return a success response + return make_response(jsonify({"message": "Review flagged successfully!"}), 200) + + except Exception as e: + # Log the error and return a 500 error response + current_app.logger.error(f"Error flagging review with ID {review_id}: {e}") + return make_response(jsonify({"error": "Database query failed"}), 500) \ No newline at end of file diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index 412af6e26b..f24acc9438 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -32,6 +32,26 @@ def add_comment(review_id, user_id, content): logger.error(f"Failed to add comment to review {review_id}: {e}") return None +# Function to like a review +def like_review(review_id): + try: + response = requests.post(f"http://api:4000/s/review/{review_id}/like") + response.raise_for_status() + return response.json() # Assuming the API returns the updated likes count or success message + except requests.exceptions.RequestException as e: + logger.error(f"Failed to like review {review_id}: {e}") + return None + +# Function to flag a review +def flag_review(review_id): + try: + response = requests.post(f"http://api:4000/s/review/{review_id}/flag") + response.raise_for_status() + return response.json() # Assuming the API returns the success message + except requests.exceptions.RequestException as e: + logger.error(f"Failed to flag review {review_id}: {e}") + return None + # Fetch companies with reviews try: results = requests.get('http://api:4000/s/companiesWithReviews').json() @@ -65,6 +85,23 @@ def add_comment(review_id, user_id, content): st.write(f"**Heading:** {review['heading']}") st.write(f"**Content:** {review['content']}") st.write(f"**Views:** {review['views']} | **Likes:** {review['likes']}") + + # Add a like button + if st.button(f"Like (Likes: {review['likes']})", key=f"like_button_{review['reviewID']}"): + like_response = like_review(review['reviewID']) + if like_response: + st.success("Liked the review!") + else: + st.error("Failed to like the review. Please try again.") + + # Add a flag button + if st.button(f"Flag this review", key=f"flag_button_{review['reviewID']}"): + flag_response = flag_review(review['reviewID']) + if flag_response: + st.success("Review flagged successfully!") + else: + st.error("Failed to flag the review. Please try again.") + st.write("---") # Fetch comments for the current review From c0541735c82102bd06c73b6afa999d086e1ff362 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Sat, 7 Dec 2024 00:24:14 -0500 Subject: [PATCH 67/75] update database --- database-files/12_CoopPlatform_Data.sql | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/database-files/12_CoopPlatform_Data.sql b/database-files/12_CoopPlatform_Data.sql index 84d14d777d..16eebc7b6c 100644 --- a/database-files/12_CoopPlatform_Data.sql +++ b/database-files/12_CoopPlatform_Data.sql @@ -261,25 +261,25 @@ INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, INSERT INTO Reviews (userID, roleID, publishedAt, reviewType, heading, content, views, likes, isFlagged) VALUES (2, 1, '2024-01-05 15:30:00', 'InterviewReport', 'Machine Learning Frameworks', 'They grilled me on machine learning frameworks like TensorFlow and PyTorch. Be ready for some deep technical discussions.', 130, 40, FALSE), -(3, 2, '2024-01-10 09:45:00', 'InterviewReport', 'Sustainability Practices in Agriculture', 'Expect detailed questions on sustainable farming techniques. They tested my knowledge of real-world agricultural challenges.', 180, 50, FALSE), +(3, 2, '2024-01-10 09:45:00', 'InterviewReport', 'Sustainability Practices in Agriculture', 'Expect detailed questions on sustainable farming techniques. They tested my knowledge of real-world agricultural challenges.', 180, 50, TRUE), (4, 2, '2024-01-15 14:20:00', 'InterviewReport', 'Sustainability Metrics', 'They focused on sustainability metrics and how I would apply them to optimize farming practices.', 120, 30, FALSE), (5, 3, '2024-01-20 11:10:00', 'InterviewReport', 'Aerospace Engineering Concepts', 'Be prepared for questions on spacecraft propulsion and satellite design. Technical, but stimulating!', 160, 45, FALSE), (6, 3, '2024-01-25 17:00:00', 'InterviewReport', 'Advanced Aerospace Technology', 'They asked about advanced aerospace technologies and how I would improve existing designs.', 150, 40, FALSE), (7, 4, '2024-02-01 08:00:00', 'InterviewReport', 'Renewable Energy Challenges', 'They asked about the challenges in renewable energy, especially regarding solar technology. Make sure to know your data.', 140, 38, FALSE), (8, 4, '2024-02-05 10:30:00', 'InterviewReport', 'Solar Energy Design', 'The interview focused on solar energy design and real-life applications of green energy.', 110, 28, FALSE), -(9, 5, '2024-02-10 13:15:00', 'InterviewReport', 'Curriculum Design in Education', 'They asked how to design curricula for diverse learners, focusing on interactive learning strategies.', 180, 50, FALSE), +(9, 5, '2024-02-10 13:15:00', 'InterviewReport', 'Curriculum Design in Education', 'They asked how to design curricula for diverse learners, focusing on interactive learning strategies.', 180, 50, TRUE), (10, 6, '2024-02-15 16:45:00', 'InterviewReport', 'Educational Content Challenges', 'Expect questions about educational content development under time constraints and adapting materials to different learning styles.', 140, 35, FALSE), (11, 7, '2024-02-20 19:20:00', 'InterviewReport', 'Clinical Trials and Data Analysis', 'The focus was on clinical trial design, including statistical methods and data analysis challenges.', 200, 55, FALSE), (12, 6, '2024-02-25 07:30:00', 'InterviewReport', 'Pharmaceutical Research Experience', 'Expect to discuss your past experience in pharmaceutical research, including data-driven decision making.', 170, 45, FALSE), (13, 7, '2024-03-01 11:50:00', 'InterviewReport', 'Urban Development Strategies', 'They asked about sustainable urban development strategies and smart city concepts.', 150, 38, FALSE), (14, 8, '2024-03-05 09:40:00', 'InterviewReport', 'Smart City Design', 'Expect to discuss your approach to designing smart city infrastructures, focusing on technological integration.', 140, 35, FALSE), (15, 9, '2024-03-10 12:25:00', 'InterviewReport', 'Water Purification Systems', 'They asked about advanced water purification technologies and challenges in real-world applications.', 130, 33, FALSE), -(16, 10, '2024-03-15 14:00:00', 'InterviewReport', 'Water Systems Engineering Problems', 'The interview involved real-life engineering problems related to water desalination and purification.', 120, 30, FALSE), +(16, 10, '2024-03-15 14:00:00', 'InterviewReport', 'Water Systems Engineering Problems', 'The interview involved real-life engineering problems related to water desalination and purification.', 120, 30, TRUE), (17, 11, '2024-03-20 15:30:00', 'InterviewReport', 'Software Development Process', 'The interview focused on software development methodologies and tools, including problem-solving during live coding challenges.', 200, 55, FALSE), (18, 12, '2024-03-25 16:45:00', 'InterviewReport', 'Coding Challenges in Software Engineering', 'Expect live coding challenges focusing on algorithms, data structures, and system design.', 180, 50, FALSE), -(19, 13, '2024-03-30 10:10:00', 'InterviewReport', 'Creative Video Production', 'Expect questions on how to manage video projects from pre-production to distribution.', 140, 38, FALSE), +(19, 13, '2024-03-30 10:10:00', 'InterviewReport', 'Creative Video Production', 'Expect questions on how to manage video projects from pre-production to distribution.', 140, 38, TRUE), (20, 14, '2024-04-01 13:00:00', 'InterviewReport', 'Creative Content Production Techniques', 'They wanted to know my approach to creative video production, including time management and collaborating with teams under tight deadlines.', 130, 35, FALSE), -(21, 15, '2024-04-05 14:30:00', 'InterviewReport', 'Robotics Engineering Solutions', 'They focused on advanced robotics engineering, including the integration of AI into robotic systems.', 190, 50, FALSE), +(21, 15, '2024-04-05 14:30:00', 'InterviewReport', 'Robotics Engineering Solutions', 'They focused on advanced robotics engineering, including the integration of AI into robotic systems.', 190, 50, TRUE), (22, 15, '2024-04-10 09:15:00', 'InterviewReport', 'Robotics Project Management', 'Expect questions on managing large-scale robotics projects, especially in an industrial setting.', 180, 48, FALSE), (23, 16, '2024-04-15 10:45:00', 'InterviewReport', 'Financial Modeling Techniques', 'Expect in-depth questions about financial modeling, with a focus on real-world applications in the financial sector.', 170, 45, FALSE), (24, 16, '2024-04-20 11:30:00', 'InterviewReport', 'Advanced Financial Analysis', 'They asked me to walk through complex financial analysis and forecasting techniques under tight deadlines.', 160, 42, FALSE), From 0d2d5c461f06ba98308b1ae52c4b5fb829385361 Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Sat, 7 Dec 2024 00:30:06 -0500 Subject: [PATCH 68/75] fix copy --- ..._Analytics_and_Trends copy.py => 3005_Analytics_and_Trends.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/pages/{3005_Analytics_and_Trends copy.py => 3005_Analytics_and_Trends.py} (100%) diff --git a/app/src/pages/3005_Analytics_and_Trends copy.py b/app/src/pages/3005_Analytics_and_Trends.py similarity index 100% rename from app/src/pages/3005_Analytics_and_Trends copy.py rename to app/src/pages/3005_Analytics_and_Trends.py From d1d7c6f33c81ac07ac4734ea85e6c1ae76858015 Mon Sep 17 00:00:00 2001 From: CChristinaFu Date: Sat, 7 Dec 2024 04:37:29 -0500 Subject: [PATCH 69/75] changes --- app/src/Home.py | 94 ++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/app/src/Home.py b/app/src/Home.py index 06521aa7c5..a542812aa5 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -1,11 +1,14 @@ ################################################## -# This is the main/entry-point file for the +# This is the main/entry-point file for the # sample application for your project ################################################## # Set up basic logging infrastructure import logging -logging.basicConfig(format='%(filename)s:%(lineno)s:%(levelname)s -- %(message)s', level=logging.INFO) + +logging.basicConfig( + format="%(filename)s:%(lineno)s:%(levelname)s -- %(message)s", level=logging.INFO +) logger = logging.getLogger(__name__) # import the main streamlit library as well @@ -15,15 +18,15 @@ # streamlit supports reguarl and wide layout (how the controls # are organized/displayed on the screen). -st.set_page_config(layout = 'wide') +st.set_page_config(layout="wide") -# If a user is at this page, we assume they are not +# If a user is at this page, we assume they are not # authenticated. So we change the 'authenticated' value -# in the streamlit session_state to false. -st.session_state['authenticated'] = False +# in the streamlit session_state to false. +st.session_state["authenticated"] = False # Use the SideBarLinks function from src/modules/nav.py to control -# the links displayed on the left-side panel. +# the links displayed on the left-side panel. # IMPORTANT: ensure src/.streamlit/config.toml sets # showSidebarNavigation = false in the [client] section SideBarLinks(show_home=True) @@ -32,52 +35,55 @@ # The major content of this page # *************************************************** -# set the title of the page and provide a simple prompt. +# set the title of the page and provide a simple prompt. logger.info("Loading the Home page of the app") -st.title('TRACE For Co Ops') -st.write('\n\n') -st.write('### HI! As which user would you like to log in?') +st.title("Welcome to COUPE") +st.write("\n\n") +st.write("### HI! As which user would you like to log in?") # For each of the user personas for which we are implementing -# functionality, we put a button on the screen that the user -# can click to MIMIC logging in as that mock user. +# functionality, we put a button on the screen that the user +# can click to MIMIC logging in as that mock user. -if st.button("Act as Sebastian, a Student Co-Op Searcher", - type = 'primary', - use_container_width=True): - st.session_state['authenticated'] = True - st.session_state['role'] = 'Co-Op searcher' - st.session_state['first_name'] = 'Sebastian' - st.session_state['id'] = '5' +if st.button( + "Act as Sebastian, a Student Co-Op Searcher", + type="primary", + use_container_width=True, +): + st.session_state["authenticated"] = True + st.session_state["role"] = "Co-Op searcher" + st.session_state["first_name"] = "Sebastian" + st.session_state["id"] = "5" logger.info("Logging in as Co-Op Searcher") - st.switch_page('pages/100_CoOp_Searcher_Home.py') + st.switch_page("pages/100_CoOp_Searcher_Home.py") -if st.button('Act as Riley, a student Co-Op Reviewer', - type = 'primary', - use_container_width=True): - st.session_state['authenticated'] = True - st.session_state['role'] = 'Co-Op reviewer' - st.session_state['id'] = '1' - st.session_state['first_name'] = 'Riley' +if st.button( + "Act as Riley, a student Co-Op Reviewer", type="primary", use_container_width=True +): + st.session_state["authenticated"] = True + st.session_state["role"] = "Co-Op reviewer" + st.session_state["id"] = "1" + st.session_state["first_name"] = "Riley" logger.info("Logging in as Co Op Reviewer") - st.switch_page('pages/200_CoOp_Reviewer_Home.py') + st.switch_page("pages/200_CoOp_Reviewer_Home.py") -if st.button('Act as Alex Admin, System Administrator', - type = 'primary', - use_container_width=True): - st.session_state['authenticated'] = True - st.session_state['role'] = 'administrator' - st.session_state['first_name'] = 'Alex' +if st.button( + "Act as Alex Admin, System Administrator", type="primary", use_container_width=True +): + st.session_state["authenticated"] = True + st.session_state["role"] = "administrator" + st.session_state["first_name"] = "Alex" logger.info("Logging in as Alex Admin, System Administrator") - st.switch_page('pages/300_System_Administrator_Home.py') - + st.switch_page("pages/300_System_Administrator_Home.py") -if st.button('Act as Annalise, an Analyist of Site Performance', - type = 'primary', - use_container_width=True): - st.session_state['authenticated'] = True - st.session_state['role'] = 'analyst' - st.session_state['first_name'] = 'Annalise' - st.switch_page('pages/400_Analyst_Home.py') +if st.button( + "Act as Annalise, an Analysist of Site Performance", + type="primary", + use_container_width=True, +): + st.session_state["authenticated"] = True + st.session_state["role"] = "administrator" + st.session_state["first_name"] = "SysAdmin" + st.switch_page("pages/20_Admin_Home.py") From 05c6f8f5999917f1832983fbf1a2684263fc1794 Mon Sep 17 00:00:00 2001 From: CChristinaFu Date: Sat, 7 Dec 2024 06:49:40 -0500 Subject: [PATCH 70/75] som changes --- app/src/.streamlit/config.toml | 3 +- app/src/Home.py | 4 +- .../pages/1001_Company_Position_Reviews.py | 118 +++++++++++------- app/src/pages/1003_Skill_Matching.py | 17 +-- app/src/pages/4001_Analytics_Page.py | 26 +++- 5 files changed, 104 insertions(+), 64 deletions(-) diff --git a/app/src/.streamlit/config.toml b/app/src/.streamlit/config.toml index bb28be97de..73191c466a 100644 --- a/app/src/.streamlit/config.toml +++ b/app/src/.streamlit/config.toml @@ -15,6 +15,5 @@ showSidebarNavigation = false [theme] # Setting some basic config options related to the theme of the app base="light" -primaryColor="#6550e6" -font="monospace" +primaryColor="#ea0000" diff --git a/app/src/Home.py b/app/src/Home.py index a542812aa5..8224eb2185 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -85,5 +85,5 @@ ): st.session_state["authenticated"] = True st.session_state["role"] = "administrator" - st.session_state["first_name"] = "SysAdmin" - st.switch_page("pages/20_Admin_Home.py") + st.session_state["first_name"] = "Annalise" + st.switch_page("pages/400_Analyst_Home.py") diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index f24acc9438..2f0dc031ee 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -10,10 +10,11 @@ SideBarLinks() # Set the header of the page -st.header('Find Company and Position Reviews') +st.header("Find Company and Position Reviews") # Access the session state for personalization -st.write(f"### Hi, {st.session_state['first_name']}.") +st.write(f"### Hi, {st.session_state.get('first_name', 'Guest')}!") + # Function to add a comment to a review def add_comment(review_id, user_id, content): @@ -27,34 +28,37 @@ def add_comment(review_id, user_id, content): }, ) response.raise_for_status() - return response.json() # Assuming the API returns the created comment or success message + return response.json() except requests.exceptions.RequestException as e: logger.error(f"Failed to add comment to review {review_id}: {e}") return None + # Function to like a review def like_review(review_id): try: response = requests.post(f"http://api:4000/s/review/{review_id}/like") response.raise_for_status() - return response.json() # Assuming the API returns the updated likes count or success message + return response.json() except requests.exceptions.RequestException as e: logger.error(f"Failed to like review {review_id}: {e}") return None + # Function to flag a review def flag_review(review_id): try: response = requests.post(f"http://api:4000/s/review/{review_id}/flag") response.raise_for_status() - return response.json() # Assuming the API returns the success message + return response.json() except requests.exceptions.RequestException as e: logger.error(f"Failed to flag review {review_id}: {e}") return None + # Fetch companies with reviews try: - results = requests.get('http://api:4000/s/companiesWithReviews').json() + results = requests.get("http://api:4000/s/companiesWithReviews").json() company_names = [item["CompanyName"] for item in results] except Exception as e: st.error("Failed to fetch company data. Please try again later.") @@ -68,7 +72,9 @@ def flag_review(review_id): if selected_company: # Fetch reviews for the selected company try: - reviews = requests.get(f'http://api:4000/s/reviewsForCompany/{selected_company}').json() + reviews = requests.get( + f"http://api:4000/s/reviewsForCompany/{selected_company}" + ).json() except Exception as e: st.error("Failed to fetch reviews. Please try again later.") logger.error(f"Error fetching reviews: {e}") @@ -79,66 +85,82 @@ def flag_review(review_id): st.write("### Reviews for this Company:") for review in reviews: - st.subheader(f"Review by User {review['userID']}") - st.write(f"**Role ID:** {review['roleID']}") - st.write(f"**Published At:** {review['publishedAt']}") - st.write(f"**Heading:** {review['heading']}") - st.write(f"**Content:** {review['content']}") - st.write(f"**Views:** {review['views']} | **Likes:** {review['likes']}") - - # Add a like button - if st.button(f"Like (Likes: {review['likes']})", key=f"like_button_{review['reviewID']}"): - like_response = like_review(review['reviewID']) - if like_response: - st.success("Liked the review!") - else: - st.error("Failed to like the review. Please try again.") - - # Add a flag button - if st.button(f"Flag this review", key=f"flag_button_{review['reviewID']}"): - flag_response = flag_review(review['reviewID']) - if flag_response: - st.success("Review flagged successfully!") - else: - st.error("Failed to flag the review. Please try again.") - - st.write("---") - - # Fetch comments for the current review + st.markdown( + f""" +
+

Review by User {review['userID']}

+

Role ID: {review['roleID']}

+

Published At: {review['publishedAt']}

+

Heading: {review['heading']}

+

Content: {review['content']}

+

Views: {review['views']} | Likes: {review['likes']}

+
+ """, + unsafe_allow_html=True, + ) + + st.markdown('
', unsafe_allow_html=True) + + # Fetch and display comments try: - comments = requests.get(f"http://api:4000/r/commentsByReview/{review['reviewID']}").json() + comments = requests.get( + f"http://api:4000/r/commentsByReview/{review['reviewID']}" + ).json() except Exception as e: st.error("Failed to fetch comments. Please try again later.") logger.error(f"Error fetching comments: {e}") comments = [] - # Display comments if comments: - st.write("#### Comments:") + st.markdown("#### Comments:", unsafe_allow_html=True) for comment in comments: - st.write(f"- **User {comment['userID']}**: {comment['content']} (Likes: {comment['likes']})") + st.markdown( + f""" +
+

User {comment['userID']}: {comment['content']}
+ Likes: {comment['likes']}

+
+ """, + unsafe_allow_html=True, + ) else: - st.write("No comments yet for this review.") + st.markdown("

No comments yet.

", unsafe_allow_html=True) # Add a form to post a new comment with st.form(key=f"add_comment_form_{review['reviewID']}"): - st.subheader("Add a Comment") - new_comment_content = st.text_area("Your Comment", key=f"comment_content_{review['reviewID']}") + st.write("#### Add a Comment") + new_comment_content = st.text_area( + "Your Comment", key=f"comment_content_{review['reviewID']}" + ) submit_comment_button = st.form_submit_button(label="Post Comment") if submit_comment_button and new_comment_content: - user_id = st.session_state.get("id") # Assuming user ID is stored in session state - comment_response = add_comment(review['reviewID'], user_id, new_comment_content) + user_id = st.session_state.get( + "id" + ) # Assuming user ID is stored in session state + comment_response = add_comment( + review["reviewID"], user_id, new_comment_content + ) if comment_response: st.success("Comment added successfully!") - # Optionally refresh comments - comments.append({ - "userID": user_id, - "content": new_comment_content, - "likes": 0, - }) else: st.error("Failed to post comment. Please try again.") + + st.markdown("
", unsafe_allow_html=True) # Close inner div + + st.markdown("
", unsafe_allow_html=True) # Close outer div else: st.write("No reviews available for this company.") else: diff --git a/app/src/pages/1003_Skill_Matching.py b/app/src/pages/1003_Skill_Matching.py index 0ffdddb18c..e6db0c4b04 100644 --- a/app/src/pages/1003_Skill_Matching.py +++ b/app/src/pages/1003_Skill_Matching.py @@ -8,13 +8,14 @@ SideBarLinks() # Set the header of the page -st.header('Find positions with matching skills') +st.header("Find positions with matching skills") # You can access the session state to make a more customized/personalized app experience st.write(f"### Hi, {st.session_state['first_name']}.") # Fetch the list of possible skills from the API -skills = requests.get('http://api:4000/s/possibleSkills').json() +skills = requests.get("http://api:4000/s/possibleSkills").json() +skills = sorted(skills) # Extract and split skillsRequired into a set of unique skills @@ -33,22 +34,24 @@ if selected_skill: try: # Send the GET request to the API endpoint with the skill - response = requests.get(f'http://api:4000/s/rolesForSkill/{selected_skill}') - + response = requests.get(f"http://api:4000/s/rolesForSkill/{selected_skill}") + # Check if the response is successful (status code 200) if response.status_code == 200: data = response.json() - + # If there is data, display it in a table if data: # Convert the data into a Pandas DataFrame for easy display - df = pd.DataFrame(data, columns=['roleName', 'companyName', 'skillsRequired']) + df = pd.DataFrame( + data, columns=["roleName", "companyName", "skillsRequired"] + ) st.write(f"### Roles that require the skill: {selected_skill}") st.dataframe(df) # Display the DataFrame in Streamlit table format else: st.warning(f"No roles found that require the skill '{selected_skill}'.") else: st.error("Failed to fetch data from the server. Please try again later.") - + except requests.exceptions.RequestException as e: st.error(f"Error fetching data: {e}") diff --git a/app/src/pages/4001_Analytics_Page.py b/app/src/pages/4001_Analytics_Page.py index 411e9b5a7f..189694e037 100644 --- a/app/src/pages/4001_Analytics_Page.py +++ b/app/src/pages/4001_Analytics_Page.py @@ -1,4 +1,5 @@ import logging + logger = logging.getLogger(__name__) import requests import pandas as pd @@ -12,10 +13,11 @@ # Call the SideBarLinks from the nav module from modules.nav import SideBarLinks + SideBarLinks() # Set the header of the page -st.header('View Analytics and Trends') +st.header("View Analytics and Trends") st.write(f"### Hi, {st.session_state['first_name']}.") # Fetch industries @@ -45,8 +47,18 @@ # Plot trends if data is valid if not st.session_state.industries.empty and not st.session_state.reviews.empty: fig, ax = plt.subplots(figsize=(10, 6)) - ax.plot(st.session_state.reviews["Industry"], st.session_state.reviews['NumReviews'], label="reviews", marker="o") - ax.plot(st.session_state.industries["Industry"], st.session_state.industries['NumCompany'], label="Companies", marker="o") + ax.plot( + st.session_state.reviews["Industry"], + st.session_state.reviews["NumReviews"], + label="reviews", + marker="o", + ) + ax.plot( + st.session_state.industries["Industry"], + st.session_state.industries["NumCompany"], + label="Companies", + marker="o", + ) ax.set_ylabel("Count") ax.set_title("Trends by Category") ax.set_xticklabels(st.session_state.industries["Industry"], rotation=45, ha="right") @@ -60,11 +72,15 @@ st.subheader("Actionable Insights") if not st.session_state.industries.empty: most_companies = st.session_state.industries.sort_values("NumCompany").iloc[-1] - st.write(f"**Industry with Most Companies**: {most_companies['Industry']} ({most_companies['NumCompany']} companies)") + st.write( + f"**Industry with Most Companies**: {most_companies['Industry']} ({most_companies['NumCompany']} companies)" + ) if not st.session_state.reviews.empty: most_reviews = st.session_state.reviews.sort_values("NumReviews").iloc[-1] - st.write(f"**Industry with Most Reviews**: {most_reviews['Industry']} ({most_reviews['NumReviews']} reviews)") + st.write( + f"**Industry with Most Reviews**: {most_reviews['Industry']} ({most_reviews['NumReviews']} reviews)" + ) # Display Data Table if "Industry" in st.session_state.industries and "Industry" in st.session_state.reviews: From be478bc7a54ec11eea283f4c2ce4b573cb286f15 Mon Sep 17 00:00:00 2001 From: CChristinaFu Date: Sat, 7 Dec 2024 09:40:31 -0500 Subject: [PATCH 71/75] changes --- .../pages/1001_Company_Position_Reviews.py | 147 +++++++----------- app/src/pages/1003_Skill_Matching.py | 1 - app/src/pages/200_CoOp_Reviewer_Home.py | 39 +++-- 3 files changed, 70 insertions(+), 117 deletions(-) diff --git a/app/src/pages/1001_Company_Position_Reviews.py b/app/src/pages/1001_Company_Position_Reviews.py index 2f0dc031ee..6b33385e15 100644 --- a/app/src/pages/1001_Company_Position_Reviews.py +++ b/app/src/pages/1001_Company_Position_Reviews.py @@ -34,28 +34,6 @@ def add_comment(review_id, user_id, content): return None -# Function to like a review -def like_review(review_id): - try: - response = requests.post(f"http://api:4000/s/review/{review_id}/like") - response.raise_for_status() - return response.json() - except requests.exceptions.RequestException as e: - logger.error(f"Failed to like review {review_id}: {e}") - return None - - -# Function to flag a review -def flag_review(review_id): - try: - response = requests.post(f"http://api:4000/s/review/{review_id}/flag") - response.raise_for_status() - return response.json() - except requests.exceptions.RequestException as e: - logger.error(f"Failed to flag review {review_id}: {e}") - return None - - # Fetch companies with reviews try: results = requests.get("http://api:4000/s/companiesWithReviews").json() @@ -85,82 +63,61 @@ def flag_review(review_id): st.write("### Reviews for this Company:") for review in reviews: - st.markdown( - f""" -
-

Review by User {review['userID']}

-

Role ID: {review['roleID']}

-

Published At: {review['publishedAt']}

-

Heading: {review['heading']}

-

Content: {review['content']}

-

Views: {review['views']} | Likes: {review['likes']}

-
- """, - unsafe_allow_html=True, - ) - - st.markdown('
', unsafe_allow_html=True) - - # Fetch and display comments - try: - comments = requests.get( - f"http://api:4000/r/commentsByReview/{review['reviewID']}" - ).json() - except Exception as e: - st.error("Failed to fetch comments. Please try again later.") - logger.error(f"Error fetching comments: {e}") - comments = [] - - if comments: - st.markdown("#### Comments:", unsafe_allow_html=True) - for comment in comments: - st.markdown( - f""" -
-

User {comment['userID']}: {comment['content']}
- Likes: {comment['likes']}

-
- """, - unsafe_allow_html=True, - ) - else: - st.markdown("

No comments yet.

", unsafe_allow_html=True) - - # Add a form to post a new comment - with st.form(key=f"add_comment_form_{review['reviewID']}"): - st.write("#### Add a Comment") - new_comment_content = st.text_area( - "Your Comment", key=f"comment_content_{review['reviewID']}" + # Expander for each review + with st.expander(f"Review by User {review['userID']}", expanded=True): + # Review details + st.write(f"**{review['heading']}**") + st.write(f"**Role ID:** {review['roleID']}") + st.write(f"**Published At:** {review['publishedAt']}") + st.write(f"**Content:** {review['content']}") + st.write( + f"**Views:** {review['views']} | **Likes:** {review['likes']}" ) - submit_comment_button = st.form_submit_button(label="Post Comment") - - if submit_comment_button and new_comment_content: - user_id = st.session_state.get( - "id" - ) # Assuming user ID is stored in session state - comment_response = add_comment( - review["reviewID"], user_id, new_comment_content - ) - if comment_response: - st.success("Comment added successfully!") - else: - st.error("Failed to post comment. Please try again.") - st.markdown("
", unsafe_allow_html=True) # Close inner div + st.divider() # Visual separator between review and comments + + # Fetch and display comments + try: + comments = requests.get( + f"http://api:4000/r/commentsByReview/{review['reviewID']}" + ).json() + except Exception as e: + st.error("Failed to fetch comments. Please try again later.") + logger.error(f"Error fetching comments: {e}") + comments = [] + + if comments: + st.write("#### Comments:") + for comment in comments: + st.write( + f"**User {comment['userID']}:** {comment['content']}" + ) + st.write(f"*Likes:* {comment['likes']}") + st.divider() + else: + st.write("No comments yet.") + + # Add comment form + with st.form(key=f"add_comment_form_{review['reviewID']}"): + st.write("#### Add a Comment") + new_comment_content = st.text_area( + "Your Comment", key=f"comment_content_{review['reviewID']}" + ) + submit_comment_button = st.form_submit_button( + label="Post Comment" + ) - st.markdown("
", unsafe_allow_html=True) # Close outer div + if submit_comment_button and new_comment_content: + user_id = st.session_state.get( + "id" + ) # Assuming user ID is stored in session state + comment_response = add_comment( + review["reviewID"], user_id, new_comment_content + ) + if comment_response: + st.success("Comment added successfully!") + else: + st.error("Failed to post comment. Please try again.") else: st.write("No reviews available for this company.") else: diff --git a/app/src/pages/1003_Skill_Matching.py b/app/src/pages/1003_Skill_Matching.py index e6db0c4b04..9e7fdef49d 100644 --- a/app/src/pages/1003_Skill_Matching.py +++ b/app/src/pages/1003_Skill_Matching.py @@ -15,7 +15,6 @@ # Fetch the list of possible skills from the API skills = requests.get("http://api:4000/s/possibleSkills").json() -skills = sorted(skills) # Extract and split skillsRequired into a set of unique skills diff --git a/app/src/pages/200_CoOp_Reviewer_Home.py b/app/src/pages/200_CoOp_Reviewer_Home.py index 2cd4bb10f2..da866673a7 100644 --- a/app/src/pages/200_CoOp_Reviewer_Home.py +++ b/app/src/pages/200_CoOp_Reviewer_Home.py @@ -1,34 +1,31 @@ import logging + logger = logging.getLogger(__name__) import streamlit as st from modules.nav import SideBarLinks -st.set_page_config(layout = 'wide') +st.set_page_config(layout="wide") # Show appropriate sidebar links for the role of the currently logged in user SideBarLinks() st.title(f"Welcome Co-op reviewer, {st.session_state['first_name']}.") -st.write('') -st.write('') -st.write('### What would you like to do today?') - -if st.button('Write a Review', - type='primary', - use_container_width=True): - st.switch_page('pages/2001_Review_Form.py') - -if st.button('View My Reviews', - type='primary', - use_container_width=True): - st.switch_page('pages/2002_My_Reviews.py') - -# if st.button('View Positions with Matching Skills', -# type='primary', +st.write("") +st.write("") +st.write("### What would you like to do today?") + +if st.button("Write a Review", type="primary", use_container_width=True): + st.switch_page("pages/2001_Review_Form.py") + +if st.button("View My Reviews", type="primary", use_container_width=True): + st.switch_page("pages/2002_My_Reviews.py") + +# if st.button('View Positions with Matching Skills', +# type='primary', # use_container_width=True): # st.switch_page('pages/1003_Skill_Matching.py') -# if st.button('Enter My Interview Experiences', -# type='primary', -# use_container_width=True): -# st.switch_page('pages/1004_Enter_Interview_Info.py') +if st.button( + "Enter My Interview Experiences", type="primary", use_container_width=True +): + st.switch_page("pages/1004_Enter_Interview_Info.py") From d1f9a3bd21275d68870aaf3e37449da665b2cdfe Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Sat, 7 Dec 2024 09:42:57 -0500 Subject: [PATCH 72/75] fixed analyst side bar --- app/src/Home.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/Home.py b/app/src/Home.py index 8224eb2185..818286fc68 100644 --- a/app/src/Home.py +++ b/app/src/Home.py @@ -84,6 +84,6 @@ use_container_width=True, ): st.session_state["authenticated"] = True - st.session_state["role"] = "administrator" + st.session_state["role"] = "analyst" st.session_state["first_name"] = "Annalise" st.switch_page("pages/400_Analyst_Home.py") From 359d217c3ae51eb25ff5360e38703fc7c813f837 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Sat, 7 Dec 2024 09:54:06 -0500 Subject: [PATCH 73/75] fixed about page --- app/src/pages/30_About.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/pages/30_About.py b/app/src/pages/30_About.py index 07a2e9aab2..462a53b9c8 100644 --- a/app/src/pages/30_About.py +++ b/app/src/pages/30_About.py @@ -2,17 +2,17 @@ from streamlit_extras.app_logo import add_logo from modules.nav import SideBarLinks + SideBarLinks() +st.sidebar.page_link("Home.py", label="Home", icon="🏠") + st.write("# About this App") + st.markdown ( """ - This is a demo app for CS 3200 Course Project. - - The goal of this demo is to provide information on the tech stack - being used as well as demo some of the features of the various platforms. + COUPE is a data-driven platform designed to revolutionize the Co-Op search process for Northeastern students by providing peer-to-peer insights into specific company experiences. While platforms like NUWorks provide job listings, they often fall short in detailing the real day-to-day life, culture, and interview dynamics students will encounter. COUPE fills this gap by giving students a space to share and access honest feedback about what it’s truly like working for various employers—covering everything from workplace culture to interview formats and application tips. - Stay tuned for more information and features to come! """ ) From 63516152f0dae1c3285d1638d6e533d4c19cd7c4 Mon Sep 17 00:00:00 2001 From: zootsuitproductions Date: Sat, 7 Dec 2024 10:17:49 -0500 Subject: [PATCH 74/75] deleted project template files --- api/backend/customers/customer_routes.py | 83 -------- api/backend/ml_models/__init__.py | 0 api/backend/ml_models/model01.py | 48 ----- api/backend/reviews copy/reviews_routes.py | 228 --------------------- api/backend/simple/playlist.py | 129 ------------ api/backend/simple/simple_routes.py | 48 ----- app/src/pages/00_Pol_Strat_Home.py | 25 --- app/src/pages/01_World_Bank_Viz.py | 41 ---- app/src/pages/02_Map_Demo.py | 104 ---------- app/src/pages/03_Simple_Chat_Bot.py | 66 ------ app/src/pages/04_Prediction.py | 38 ---- app/src/pages/10_USAID_Worker_Home.py | 30 --- app/src/pages/11_Prediction.py | 38 ---- app/src/pages/12_API_Test.py | 25 --- app/src/pages/13_Classification.py | 57 ------ app/src/pages/21_ML_Model_Mgmt.py | 28 --- app/src/pages/400_Alex_Admin_Home.py | 30 --- 17 files changed, 1018 deletions(-) delete mode 100644 api/backend/customers/customer_routes.py delete mode 100644 api/backend/ml_models/__init__.py delete mode 100644 api/backend/ml_models/model01.py delete mode 100644 api/backend/reviews copy/reviews_routes.py delete mode 100644 api/backend/simple/playlist.py delete mode 100644 api/backend/simple/simple_routes.py delete mode 100644 app/src/pages/00_Pol_Strat_Home.py delete mode 100644 app/src/pages/01_World_Bank_Viz.py delete mode 100644 app/src/pages/02_Map_Demo.py delete mode 100644 app/src/pages/03_Simple_Chat_Bot.py delete mode 100644 app/src/pages/04_Prediction.py delete mode 100644 app/src/pages/10_USAID_Worker_Home.py delete mode 100644 app/src/pages/11_Prediction.py delete mode 100644 app/src/pages/12_API_Test.py delete mode 100644 app/src/pages/13_Classification.py delete mode 100644 app/src/pages/21_ML_Model_Mgmt.py delete mode 100644 app/src/pages/400_Alex_Admin_Home.py diff --git a/api/backend/customers/customer_routes.py b/api/backend/customers/customer_routes.py deleted file mode 100644 index 4fda460220..0000000000 --- a/api/backend/customers/customer_routes.py +++ /dev/null @@ -1,83 +0,0 @@ -######################################################## -# Sample customers blueprint of endpoints -# Remove this file if you are not using it in your project -######################################################## -from flask import Blueprint -from flask import request -from flask import jsonify -from flask import make_response -from flask import current_app -from backend.db_connection import db -from backend.ml_models.model01 import predict - -#------------------------------------------------------------ -# Create a new Blueprint object, which is a collection of -# routes. -customers = Blueprint('customers', __name__) - - -#------------------------------------------------------------ -# Get all customers from the system -@customers.route('/customers', methods=['GET']) -def get_customers(): - - cursor = db.get_db().cursor() - cursor.execute('''SELECT id, company, last_name, - first_name, job_title, business_phone FROM customers - ''') - - theData = cursor.fetchall() - - the_response = make_response(jsonify(theData)) - the_response.status_code = 200 - return the_response - -#------------------------------------------------------------ -# Update customer info for customer with particular userID -# Notice the manner of constructing the query. -@customers.route('/customers', methods=['PUT']) -def update_customer(): - current_app.logger.info('PUT /customers route') - cust_info = request.json - cust_id = cust_info['id'] - first = cust_info['first_name'] - last = cust_info['last_name'] - company = cust_info['company'] - - query = 'UPDATE customers SET first_name = %s, last_name = %s, company = %s where id = %s' - data = (first, last, company, cust_id) - cursor = db.get_db().cursor() - r = cursor.execute(query, data) - db.get_db().commit() - return 'customer updated!' - -#------------------------------------------------------------ -# Get customer detail for customer with particular userID -# Notice the manner of constructing the query. -@customers.route('/customers/', methods=['GET']) -def get_customer(userID): - current_app.logger.info('GET /customers/ route') - cursor = db.get_db().cursor() - cursor.execute('SELECT id, first_name, last_name FROM customers WHERE id = {0}'.format(userID)) - - theData = cursor.fetchall() - - the_response = make_response(jsonify(theData)) - the_response.status_code = 200 - return the_response - -#------------------------------------------------------------ -# Makes use of the very simple ML model in to predict a value -# and returns it to the user -@customers.route('/prediction//', methods=['GET']) -def predict_value(var01, var02): - current_app.logger.info(f'var01 = {var01}') - current_app.logger.info(f'var02 = {var02}') - - returnVal = predict(var01, var02) - return_dict = {'result': returnVal} - - the_response = make_response(jsonify(return_dict)) - the_response.status_code = 200 - the_response.mimetype = 'application/json' - return the_response \ No newline at end of file diff --git a/api/backend/ml_models/__init__.py b/api/backend/ml_models/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/api/backend/ml_models/model01.py b/api/backend/ml_models/model01.py deleted file mode 100644 index 368152fbab..0000000000 --- a/api/backend/ml_models/model01.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -model01.py is an example of how to access model parameter values that you are storing -in the database and use them to make a prediction when a route associated with prediction is -accessed. -""" -from backend.db_connection import db -import numpy as np -import logging - - -def train(): - """ - You could have a function that performs training from scratch as well as testing (see below). - It could be activated from a route for an "administrator role" or something similar. - """ - return 'Training the model' - -def test(): - return 'Testing the model' - -def predict(var01, var02): - """ - Retreives model parameters from the database and uses them for real-time prediction - """ - # get a database cursor - cursor = db.get_db().cursor() - # get the model params from the database - query = 'SELECT beta_vals FROM model1_params ORDER BY sequence_number DESC LIMIT 1' - cursor.execute(query) - return_val = cursor.fetchone() - - params = return_val['beta_vals'] - logging.info(f'params = {params}') - logging.info(f'params datatype = {type(params)}') - - # turn the values from the database into a numpy array - params_array = np.array(list(map(float, params[1:-1].split(',')))) - logging.info(f'params array = {params_array}') - logging.info(f'params_array datatype = {type(params_array)}') - - # turn the variables sent from the UI into a numpy array - input_array = np.array([1.0, float(var01), float(var02)]) - - # calculate the dot product (since this is a fake regression) - prediction = np.dot(params_array, input_array) - - return prediction - diff --git a/api/backend/reviews copy/reviews_routes.py b/api/backend/reviews copy/reviews_routes.py deleted file mode 100644 index 9fb00d3d23..0000000000 --- a/api/backend/reviews copy/reviews_routes.py +++ /dev/null @@ -1,228 +0,0 @@ -######################################################## -# Sample customers blueprint of endpoints -# Remove this file if you are not using it in your project -######################################################## - -from flask import Blueprint -from flask import request -from flask import jsonify -from flask import make_response -from flask import current_app -from backend.db_connection import db - -#------------------------------------------------------------ -# Create a new Blueprint object, which is a collection of -# routes. -reviews = Blueprint('reviews', __name__) - -#------------------------------------------------------------ -# Get all the products from the database, package them up, -# and return them to the client -@reviews.route('/products', methods=['GET']) -def get_products(): - query = ''' - SELECT - r.reviewID, - r.roleID, - r.createdAt, - r.updatedAt, - r.publishedAt, - r.reviewType, - r.heading, - r.content, - r.views, - r.likes, - r.isFlagged -FROM - Reviews r -WHERE - r.userID = ; - ''' - - # get a cursor object from the database - cursor = db.get_db().cursor() - - # use cursor to query the database for a list of products - cursor.execute(query) - - # fetch all the data from the cursor - # The cursor will return the data as a - # Python Dictionary - theData = cursor.fetchall() - - # Create a HTTP Response object and add results of the query to it - # after "jasonify"-ing it. - response = make_response(jsonify(theData)) - # set the proper HTTP Status code of 200 (meaning all good) - response.status_code = 200 - # send the response back to the client - return response - -# ------------------------------------------------------------ -# get product information about a specific product -# notice that the route takes and then you see id -# as a parameter to the function. This is one way to send -# parameterized information into the route handler. -@reviews.route('/reviewsByUser/', methods=['GET']) -def get_product_detail (id): - - query = f''' - SELECT - r.reviewID, - r.roleID, - r.createdAt, - r.updatedAt, - r.publishedAt, - r.reviewType, - r.heading, - r.content, - r.views, - r.likes, - r.isFlagged -FROM - Reviews r -WHERE - r.userID = {str(id)}; - ''' - - # logging the query for debugging purposes. - # The output will appear in the Docker logs output - # This line has nothing to do with actually executing the query... - # It is only for debugging purposes. - current_app.logger.info(f'GET /product/ query={query}') - - # get the database connection, execute the query, and - # fetch the results as a Python Dictionary - cursor = db.get_db().cursor() - cursor.execute(query) - theData = cursor.fetchall() - - # Another example of logging for debugging purposes. - # You can see if the data you're getting back is what you expect. - current_app.logger.info(f'GET /product/ Result of query = {theData}') - - response = make_response(jsonify(theData)) - response.status_code = 200 - return response - -# ------------------------------------------------------------ -# Get the top 5 most expensive products from the database -@reviews.route('/mostExpensive') -def get_most_pop_products(): - - query = ''' - SELECT product_code, - product_name, - list_price, - reorder_level - FROM products - ORDER BY list_price DESC - LIMIT 5 - ''' - - # Same process as handler above - cursor = db.get_db().cursor() - cursor.execute(query) - theData = cursor.fetchall() - - response = make_response(jsonify(theData)) - response.status_code = 200 - return response - -# ------------------------------------------------------------ -# Route to get the 10 most expensive items from the -# database. -@reviews.route('/tenMostExpensive', methods=['GET']) -def get_10_most_expensive_products(): - - query = ''' - SELECT product_code, - product_name, - list_price, - reorder_level - FROM products - ORDER BY list_price DESC - LIMIT 10 - ''' - - # Same process as above - cursor = db.get_db().cursor() - cursor.execute(query) - theData = cursor.fetchall() - - response = make_response(jsonify(theData)) - response.status_code = 200 - return response - - -# ------------------------------------------------------------ -# This is a POST route to add a new product. -# Remember, we are using POST routes to create new entries -# in the database. -@reviews.route('/product', methods=['POST']) -def add_new_product(): - - # In a POST request, there is a - # collecting data from the request object - the_data = request.json - current_app.logger.info(the_data) - - #extracting the variable - name = the_data['product_name'] - description = the_data['product_description'] - price = the_data['product_price'] - category = the_data['product_category'] - - query = f''' - INSERT INTO products (product_name, - description, - category, - list_price) - VALUES ('{name}', '{description}', '{category}', {str(price)}) - ''' - # TODO: Make sure the version of the query above works properly - # Constructing the query - # query = 'insert into products (product_name, description, category, list_price) values ("' - # query += name + '", "' - # query += description + '", "' - # query += category + '", ' - # query += str(price) + ')' - current_app.logger.info(query) - - # executing and committing the insert statement - cursor = db.get_db().cursor() - cursor.execute(query) - db.get_db().commit() - - response = make_response("Successfully added product") - response.status_code = 200 - return response - -# ------------------------------------------------------------ -### Get all product categories -@reviews.route('/categories', methods = ['GET']) -def get_all_categories(): - query = ''' - SELECT DISTINCT category AS label, category as value - FROM products - WHERE category IS NOT NULL - ORDER BY category - ''' - - cursor = db.get_db().cursor() - cursor.execute(query) - theData = cursor.fetchall() - - response = make_response(jsonify(theData)) - response.status_code = 200 - return response - -# ------------------------------------------------------------ -# This is a stubbed route to update a product in the catalog -# The SQL query would be an UPDATE. -@reviews.route('/product', methods = ['PUT']) -def update_product(): - product_info = request.json - current_app.logger.info(product_info) - - return "Success" \ No newline at end of file diff --git a/api/backend/simple/playlist.py b/api/backend/simple/playlist.py deleted file mode 100644 index a9e7a9ef03..0000000000 --- a/api/backend/simple/playlist.py +++ /dev/null @@ -1,129 +0,0 @@ -# ------------------------------------------------------------ -# Sample data for testing generated by ChatGPT -# ------------------------------------------------------------ - -sample_playlist_data = { - "playlist": { - "id": "37i9dQZF1DXcBWIGoYBM5M", - "name": "Chill Hits", - "description": "Relax and unwind with the latest chill hits.", - "owner": { - "id": "spotify_user_123", - "display_name": "Spotify User" - }, - "tracks": { - "items": [ - { - "track": { - "id": "3n3Ppam7vgaVa1iaRUc9Lp", - "name": "Lose Yourself", - "artists": [ - { - "id": "1dfeR4HaWDbWqFHLkxsg1d", - "name": "Eminem" - } - ], - "album": { - "id": "1ATL5GLyefJaxhQzSPVrLX", - "name": "8 Mile" - }, - "duration_ms": 326000, - "track_number": 1, - "disc_number": 1, - "preview_url": "https://p.scdn.co/mp3-preview/lose-yourself.mp3", - "uri": "spotify:track:3n3Ppam7vgaVa1iaRUc9Lp" - } - }, - { - "track": { - "id": "7ouMYWpwJ422jRcDASZB7P", - "name": "Blinding Lights", - "artists": [ - { - "id": "0fW8E0XdT6aG9aFh6jGpYo", - "name": "The Weeknd" - } - ], - "album": { - "id": "1ATL5GLyefJaxhQzSPVrLX", - "name": "After Hours" - }, - "duration_ms": 200040, - "track_number": 9, - "disc_number": 1, - "preview_url": "https://p.scdn.co/mp3-preview/blinding-lights.mp3", - "uri": "spotify:track:7ouMYWpwJ422jRcDASZB7P" - } - }, - { - "track": { - "id": "4uLU6hMCjMI75M1A2tKUQC", - "name": "Shape of You", - "artists": [ - { - "id": "6eUKZXaKkcviH0Ku9w2n3V", - "name": "Ed Sheeran" - } - ], - "album": { - "id": "3fMbdgg4jU18AjLCKBhRSm", - "name": "Divide" - }, - "duration_ms": 233713, - "track_number": 4, - "disc_number": 1, - "preview_url": "https://p.scdn.co/mp3-preview/shape-of-you.mp3", - "uri": "spotify:track:4uLU6hMCjMI75M1A2tKUQC" - } - }, - { - "track": { - "id": "0VjIjW4GlUZAMYd2vXMi3b", - "name": "Levitating", - "artists": [ - { - "id": "4tZwfgrHOc3mvqYlEYSvVi", - "name": "Dua Lipa" - } - ], - "album": { - "id": "7dGJo4pcD2V6oG8kP0tJRR", - "name": "Future Nostalgia" - }, - "duration_ms": 203693, - "track_number": 5, - "disc_number": 1, - "preview_url": "https://p.scdn.co/mp3-preview/levitating.mp3", - "uri": "spotify:track:0VjIjW4GlUZAMYd2vXMi3b" - } - }, - { - "track": { - "id": "6habFhsOp2NvshLv26DqMb", - "name": "Sunflower", - "artists": [ - { - "id": "1dfeR4HaWDbWqFHLkxsg1d", - "name": "Post Malone" - }, - { - "id": "0C8ZW7ezQVs4URX5aX7Kqx", - "name": "Swae Lee" - } - ], - "album": { - "id": "6k3hyp4efgfHP5GMVd3Agw", - "name": "Spider-Man: Into the Spider-Verse (Soundtrack)" - }, - "duration_ms": 158000, - "track_number": 3, - "disc_number": 1, - "preview_url": "https://p.scdn.co/mp3-preview/sunflower.mp3", - "uri": "spotify:track:6habFhsOp2NvshLv26DqMb" - } - } - ] - }, - "uri": "spotify:playlist:37i9dQZF1DXcBWIGoYBM5M" - } -} \ No newline at end of file diff --git a/api/backend/simple/simple_routes.py b/api/backend/simple/simple_routes.py deleted file mode 100644 index 8685fbac76..0000000000 --- a/api/backend/simple/simple_routes.py +++ /dev/null @@ -1,48 +0,0 @@ -from flask import Blueprint, request, jsonify, make_response, current_app, redirect, url_for -import json -from backend.db_connection import db -from backend.simple.playlist import sample_playlist_data - -# This blueprint handles some basic routes that you can use for testing -simple_routes = Blueprint('simple_routes', __name__) - - -# ------------------------------------------------------------ -# / is the most basic route -# Once the api container is started, in a browser, go to -# localhost:4000/playlist -@simple_routes.route('/') -def welcome(): - current_app.logger.info('GET / handler') - welcome_message = '

Welcome to the CS 3200 Project Template REST API' - response = make_response(welcome_message) - response.status_code = 200 - return response - -# ------------------------------------------------------------ -# /playlist returns the sample playlist data contained in playlist.py -# (imported above) -@simple_routes.route('/playlist') -def get_playlist_data(): - current_app.logger.info('GET /playlist handler') - response = make_response(jsonify(sample_playlist_data)) - response.status_code = 200 - return response - -# ------------------------------------------------------------ -@simple_routes.route('/niceMesage', methods = ['GET']) -def affirmation(): - message = ''' -

Think about it...

-
- You only need to be 1% better today than you were yesterday! - ''' - response = make_response(message) - response.status_code = 200 - return response - -# ------------------------------------------------------------ -# Demonstrates how to redirect from one route to another. -@simple_routes.route('/message') -def mesage(): - return redirect(url_for(affirmation)) \ No newline at end of file diff --git a/app/src/pages/00_Pol_Strat_Home.py b/app/src/pages/00_Pol_Strat_Home.py deleted file mode 100644 index 3d02f25552..0000000000 --- a/app/src/pages/00_Pol_Strat_Home.py +++ /dev/null @@ -1,25 +0,0 @@ -import logging -logger = logging.getLogger(__name__) - -import streamlit as st -from modules.nav import SideBarLinks - -st.set_page_config(layout = 'wide') - -# Show appropriate sidebar links for the role of the currently logged in user -SideBarLinks() - -st.title(f"Welcome Political Strategist, {st.session_state['first_name']}.") -st.write('') -st.write('') -st.write('### What would you like to do today?') - -if st.button('View World Bank Data Visualization', - type='primary', - use_container_width=True): - st.switch_page('pages/01_World_Bank_Viz.py') - -if st.button('View World Map Demo', - type='primary', - use_container_width=True): - st.switch_page('pages/02_Map_Demo.py') \ No newline at end of file diff --git a/app/src/pages/01_World_Bank_Viz.py b/app/src/pages/01_World_Bank_Viz.py deleted file mode 100644 index a34cbb1529..0000000000 --- a/app/src/pages/01_World_Bank_Viz.py +++ /dev/null @@ -1,41 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import pandas as pd -import streamlit as st -from streamlit_extras.app_logo import add_logo -import world_bank_data as wb -import matplotlib.pyplot as plt -import numpy as np -import plotly.express as px -from modules.nav import SideBarLinks - -# Call the SideBarLinks from the nav module in the modules directory -SideBarLinks() - -# set the header of the page -st.header('World Bank Data') - -# You can access the session state to make a more customized/personalized app experience -st.write(f"### Hi, {st.session_state['first_name']}.") - -# get the countries from the world bank data -with st.echo(code_location='above'): - countries:pd.DataFrame = wb.get_countries() - - st.dataframe(countries) - -# the with statment shows the code for this block above it -with st.echo(code_location='above'): - arr = np.random.normal(1, 1, size=100) - test_plot, ax = plt.subplots() - ax.hist(arr, bins=20) - - st.pyplot(test_plot) - - -with st.echo(code_location='above'): - slim_countries = countries[countries['incomeLevel'] != 'Aggregates'] - data_crosstab = pd.crosstab(slim_countries['region'], - slim_countries['incomeLevel'], - margins = False) - st.table(data_crosstab) diff --git a/app/src/pages/02_Map_Demo.py b/app/src/pages/02_Map_Demo.py deleted file mode 100644 index 5ca09a9633..0000000000 --- a/app/src/pages/02_Map_Demo.py +++ /dev/null @@ -1,104 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import streamlit as st -from streamlit_extras.app_logo import add_logo -import pandas as pd -import pydeck as pdk -from urllib.error import URLError -from modules.nav import SideBarLinks - -SideBarLinks() - -# add the logo -add_logo("assets/logo.png", height=400) - -# set up the page -st.markdown("# Mapping Demo") -st.sidebar.header("Mapping Demo") -st.write( - """This Mapping Demo is from the Streamlit Documentation. It shows how to use -[`st.pydeck_chart`](https://docs.streamlit.io/library/api-reference/charts/st.pydeck_chart) -to display geospatial data.""" -) - - -@st.cache_data -def from_data_file(filename): - url = ( - "http://raw.githubusercontent.com/streamlit/" - "example-data/master/hello/v1/%s" % filename - ) - return pd.read_json(url) - - -try: - ALL_LAYERS = { - "Bike Rentals": pdk.Layer( - "HexagonLayer", - data=from_data_file("bike_rental_stats.json"), - get_position=["lon", "lat"], - radius=200, - elevation_scale=4, - elevation_range=[0, 1000], - extruded=True, - ), - "Bart Stop Exits": pdk.Layer( - "ScatterplotLayer", - data=from_data_file("bart_stop_stats.json"), - get_position=["lon", "lat"], - get_color=[200, 30, 0, 160], - get_radius="[exits]", - radius_scale=0.05, - ), - "Bart Stop Names": pdk.Layer( - "TextLayer", - data=from_data_file("bart_stop_stats.json"), - get_position=["lon", "lat"], - get_text="name", - get_color=[0, 0, 0, 200], - get_size=15, - get_alignment_baseline="'bottom'", - ), - "Outbound Flow": pdk.Layer( - "ArcLayer", - data=from_data_file("bart_path_stats.json"), - get_source_position=["lon", "lat"], - get_target_position=["lon2", "lat2"], - get_source_color=[200, 30, 0, 160], - get_target_color=[200, 30, 0, 160], - auto_highlight=True, - width_scale=0.0001, - get_width="outbound", - width_min_pixels=3, - width_max_pixels=30, - ), - } - st.sidebar.markdown("### Map Layers") - selected_layers = [ - layer - for layer_name, layer in ALL_LAYERS.items() - if st.sidebar.checkbox(layer_name, True) - ] - if selected_layers: - st.pydeck_chart( - pdk.Deck( - map_style="mapbox://styles/mapbox/light-v9", - initial_view_state={ - "latitude": 37.76, - "longitude": -122.4, - "zoom": 11, - "pitch": 50, - }, - layers=selected_layers, - ) - ) - else: - st.error("Please choose at least one layer above.") -except URLError as e: - st.error( - """ - **This demo requires internet access.** - Connection error: %s - """ - % e.reason - ) diff --git a/app/src/pages/03_Simple_Chat_Bot.py b/app/src/pages/03_Simple_Chat_Bot.py deleted file mode 100644 index fa8db58e84..0000000000 --- a/app/src/pages/03_Simple_Chat_Bot.py +++ /dev/null @@ -1,66 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import streamlit as st -from streamlit_extras.app_logo import add_logo -import numpy as np -import random -import time -from modules.nav import SideBarLinks - -SideBarLinks() - -def response_generator(): - response = random.choice ( - [ - "Hello there! How can I assist you today?", - "Hi, human! Is there anything I can help you with?", - "Do you need help?", - ] - ) - for word in response.split(): - yield word + " " - time.sleep(0.05) -#----------------------------------------------------------------------- - -st.set_page_config (page_title="Sample Chat Bot", page_icon="🤖") -add_logo("assets/logo.png", height=400) - -st.title("Echo Bot 🤖") - -st.markdown(""" - Currently, this chat bot only returns a random message from the following list: - - Hello there! How can I assist you today? - - Hi, human! Is there anything I can help you with? - - Do you need help? - """ - ) - - -# Initialize chat history -if "messages" not in st.session_state: - st.session_state.messages = [] - -# Display chat message from history on app rerun -for message in st.session_state.messages: - with st.chat_message(message["role"]): - st.markdown(message["content"]) - -# React to user input -if prompt := st.chat_input("What is up?"): - # Display user message in chat message container - with st.chat_message("user"): - st.markdown(prompt) - - # Add user message to chat history - st.session_state.messages.append({"role": "user", "content": prompt}) - - response = f"Echo: {prompt}" - - # Display assistant response in chat message container - with st.chat_message("assistant"): - # st.markdown(response) - response = st.write_stream(response_generator()) - - # Add assistant response to chat history - st.session_state.messages.append({"role": "assistant", "content": response}) - diff --git a/app/src/pages/04_Prediction.py b/app/src/pages/04_Prediction.py deleted file mode 100644 index a5a322a2f4..0000000000 --- a/app/src/pages/04_Prediction.py +++ /dev/null @@ -1,38 +0,0 @@ -import logging -logger = logging.getLogger(__name__) - -import streamlit as st -from modules.nav import SideBarLinks -import requests - -st.set_page_config(layout = 'wide') - -# Display the appropriate sidebar links for the role of the logged in user -SideBarLinks() - -st.title('Prediction with Regression') - -# create a 2 column layout -col1, col2 = st.columns(2) - -# add one number input for variable 1 into column 1 -with col1: - var_01 = st.number_input('Variable 01:', - step=1) - -# add another number input for variable 2 into column 2 -with col2: - var_02 = st.number_input('Variable 02:', - step=1) - -logger.info(f'var_01 = {var_01}') -logger.info(f'var_02 = {var_02}') - -# add a button to use the values entered into the number field to send to the -# prediction function via the REST API -if st.button('Calculate Prediction', - type='primary', - use_container_width=True): - results = requests.get(f'http://api:4000/c/prediction/{var_01}/{var_02}').json() - st.dataframe(results) - \ No newline at end of file diff --git a/app/src/pages/10_USAID_Worker_Home.py b/app/src/pages/10_USAID_Worker_Home.py deleted file mode 100644 index d7b230384c..0000000000 --- a/app/src/pages/10_USAID_Worker_Home.py +++ /dev/null @@ -1,30 +0,0 @@ -import logging -logger = logging.getLogger(__name__) - -import streamlit as st -from modules.nav import SideBarLinks - -st.set_page_config(layout = 'wide') - -# Show appropriate sidebar links for the role of the currently logged in user -SideBarLinks() - -st.title(f"Welcome USAID Worker, {st.session_state['first_name']}.") -st.write('') -st.write('') -st.write('### What would you like to do today?') - -if st.button('Predict Value Based on Regression Model', - type='primary', - use_container_width=True): - st.switch_page('pages/11_Prediction.py') - -if st.button('View the Simple API Demo', - type='primary', - use_container_width=True): - st.switch_page('pages/12_API_Test.py') - -if st.button("View Classification Demo", - type='primary', - use_container_width=True): - st.switch_page('pages/13_Classification.py') \ No newline at end of file diff --git a/app/src/pages/11_Prediction.py b/app/src/pages/11_Prediction.py deleted file mode 100644 index a5a322a2f4..0000000000 --- a/app/src/pages/11_Prediction.py +++ /dev/null @@ -1,38 +0,0 @@ -import logging -logger = logging.getLogger(__name__) - -import streamlit as st -from modules.nav import SideBarLinks -import requests - -st.set_page_config(layout = 'wide') - -# Display the appropriate sidebar links for the role of the logged in user -SideBarLinks() - -st.title('Prediction with Regression') - -# create a 2 column layout -col1, col2 = st.columns(2) - -# add one number input for variable 1 into column 1 -with col1: - var_01 = st.number_input('Variable 01:', - step=1) - -# add another number input for variable 2 into column 2 -with col2: - var_02 = st.number_input('Variable 02:', - step=1) - -logger.info(f'var_01 = {var_01}') -logger.info(f'var_02 = {var_02}') - -# add a button to use the values entered into the number field to send to the -# prediction function via the REST API -if st.button('Calculate Prediction', - type='primary', - use_container_width=True): - results = requests.get(f'http://api:4000/c/prediction/{var_01}/{var_02}').json() - st.dataframe(results) - \ No newline at end of file diff --git a/app/src/pages/12_API_Test.py b/app/src/pages/12_API_Test.py deleted file mode 100644 index 93a97e11eb..0000000000 --- a/app/src/pages/12_API_Test.py +++ /dev/null @@ -1,25 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import streamlit as st -import requests -from streamlit_extras.app_logo import add_logo -from modules.nav import SideBarLinks - -SideBarLinks() - -st.write("# Accessing a REST API from Within Streamlit") - -""" -Simply retrieving data from a REST api running in a separate Docker Container. - -If the container isn't running, this will be very unhappy. But the Streamlit app -should not totally die. -""" -data = {} -try: - data = requests.get('http://api:4000/p/products').json() -except: - st.write("**Important**: Could not connect to sample api, so using dummy data.") - data = {"a":{"b": "123", "c": "hello"}, "z": {"b": "456", "c": "goodbye"}} - -st.dataframe(data) diff --git a/app/src/pages/13_Classification.py b/app/src/pages/13_Classification.py deleted file mode 100644 index be2535c49d..0000000000 --- a/app/src/pages/13_Classification.py +++ /dev/null @@ -1,57 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import streamlit as st -import pandas as pd -from sklearn import datasets -from sklearn.ensemble import RandomForestClassifier -from streamlit_extras.app_logo import add_logo -from modules.nav import SideBarLinks - -SideBarLinks() - -st.write(""" -# Simple Iris Flower Prediction App - -This example is borrowed from [The Data Professor](https://github.com/dataprofessor/streamlit_freecodecamp/tree/main/app_7_classification_iris) - -This app predicts the **Iris flower** type! -""") - -st.sidebar.header('User Input Parameters') - -def user_input_features(): - sepal_length = st.sidebar.slider('Sepal length', 4.3, 7.9, 5.4) - sepal_width = st.sidebar.slider('Sepal width', 2.0, 4.4, 3.4) - petal_length = st.sidebar.slider('Petal length', 1.0, 6.9, 1.3) - petal_width = st.sidebar.slider('Petal width', 0.1, 2.5, 0.2) - data = {'sepal_length': sepal_length, - 'sepal_width': sepal_width, - 'petal_length': petal_length, - 'petal_width': petal_width} - features = pd.DataFrame(data, index=[0]) - return features - -df = user_input_features() - -st.subheader('User Input parameters') -st.write(df) - -iris = datasets.load_iris() -X = iris.data -Y = iris.target - -clf = RandomForestClassifier() -clf.fit(X, Y) - -prediction = clf.predict(df) -prediction_proba = clf.predict_proba(df) - -st.subheader('Class labels and their corresponding index number') -st.write(iris.target_names) - -st.subheader('Prediction') -st.write(iris.target_names[prediction]) -#st.write(prediction) - -st.subheader('Prediction Probability') -st.write(prediction_proba) \ No newline at end of file diff --git a/app/src/pages/21_ML_Model_Mgmt.py b/app/src/pages/21_ML_Model_Mgmt.py deleted file mode 100644 index 148978c24b..0000000000 --- a/app/src/pages/21_ML_Model_Mgmt.py +++ /dev/null @@ -1,28 +0,0 @@ -import logging -logger = logging.getLogger(__name__) -import streamlit as st -from modules.nav import SideBarLinks -import requests - -st.set_page_config(layout = 'wide') - -SideBarLinks() - -st.title('App Administration Page') - -st.write('\n\n') -st.write('## Model 1 Maintenance') - -st.button("Train Model 01", - type = 'primary', - use_container_width=True) - -st.button('Test Model 01', - type = 'primary', - use_container_width=True) - -if st.button('Model 1 - get predicted value for 10, 25', - type = 'primary', - use_container_width=True): - results = requests.get('http://api:4000/c/prediction/10/25').json() - st.dataframe(results) diff --git a/app/src/pages/400_Alex_Admin_Home.py b/app/src/pages/400_Alex_Admin_Home.py deleted file mode 100644 index 8cd15313f8..0000000000 --- a/app/src/pages/400_Alex_Admin_Home.py +++ /dev/null @@ -1,30 +0,0 @@ -import streamlit as st -import logging - -logging.basicConfig(level=logging.INFO) - -def alex_admin_home(): - st.title("Welcome, Alex (Admin)") - st.write("Choose one of the following options to access admin functionalities:") - - if st.button("Go to Admin Dashboard", type="primary", use_container_width=True): - logging.info("Navigating to 3101_Admin_Dashboard") - st.switch_page('pages/3101_Admin_Dashboard.py') - - if st.button("Go to Content Moderation Panel", type="primary", use_container_width=True): - logging.info("Navigating to 3102_Content_Moderation") - st.switch_page('pages/3102_Content_Moderation.py') - - if st.button("Go to Company and Role Manager", type="primary", use_container_width=True): - logging.info("Navigating to 3103_Company_Role_Manager") - st.switch_page('pages/3103_Company_Role_Manager.py') - - if st.button("Go to Feedback and Feature Tracker", type="primary", use_container_width=True): - logging.info("Navigating to 3104_Feedback_Feature_Tracker") - st.switch_page('pages/3104_Feedback_Feature_Tracker.py') - - if st.button("Go to Analytics and Trends Page", type="primary", use_container_width=True): - logging.info("Navigating to 3105_Analytics_Trends") - st.switch_page('pages/3105_Analytics_Trends.py') - -alex_admin_home() \ No newline at end of file From d032601dfd294216be233af9dc2b1e81cf37085c Mon Sep 17 00:00:00 2001 From: Ren Yin <147033895+R-Yin-217@users.noreply.github.com> Date: Sat, 7 Dec 2024 10:19:52 -0500 Subject: [PATCH 75/75] update companies --- app/src/pages/3002_Flagged_Posts.py | 1 + app/src/pages/3003_Company_Profiles.py | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/pages/3002_Flagged_Posts.py b/app/src/pages/3002_Flagged_Posts.py index 2992b956b8..2084425544 100644 --- a/app/src/pages/3002_Flagged_Posts.py +++ b/app/src/pages/3002_Flagged_Posts.py @@ -34,6 +34,7 @@ if "timestamp" not in st.session_state: st.session_state.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + # Streamlit app st.title("Flagged Posts Review Interface") diff --git a/app/src/pages/3003_Company_Profiles.py b/app/src/pages/3003_Company_Profiles.py index fd0623624d..1c2aabbef7 100644 --- a/app/src/pages/3003_Company_Profiles.py +++ b/app/src/pages/3003_Company_Profiles.py @@ -83,9 +83,6 @@ def highlight_row(row): else: st.dataframe(company_df) -st.subheader("Update Company Profiles") - -st.subheader("Delete Company Profiles") st.subheader("Edit Company Profiles")