diff --git a/.gitignore b/.gitignore index 70f3b41b1..6b2baa272 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ node_modules/ *.ipynb* courses20.xml .coverage +compose-dev.yaml +rpi_data/get-summer-2023-2.sh +rpi_data/summer-20232.csv diff --git a/docker-compose.yml b/docker-compose.yml index a5c2af7f2..4a49c90a3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,3 +29,4 @@ services: restart: unless-stopped container_name: yacs_db image: postgres:12-alpine + diff --git a/rpi_data/pathwayV2.json b/rpi_data/pathwayV2.json new file mode 100644 index 000000000..9694108c6 --- /dev/null +++ b/rpi_data/pathwayV2.json @@ -0,0 +1,1161 @@ +[ + { + "Category Name": [ + "Arts / Designs" + ], + "Pathways": [ + { + "Name": [ + "Creative Design and Innovation" + ], + "Choose one of the following": [ + "IHSS 1960 - Remixing in Digital Culture", + "IHSS 1960 - Worlds on Display", + "IHSS 1960 - Game Sound and Musical Play", + "ARTS 1020 - Digital Imaging", + "ARTS 1030 - Digital Filmmaking", + "ARTS 1380 - Fundamentals of Music and Sound", + "IHSS 1170 - History of Animation", + "IHSS 1700 - Songwriting Workshop", + "IHSS 1040 - Documentary in the 21st Century Identity Production" + ], + "Choose remaining credits from the following": [ + "COMM 4960 - Color Theory", + "ARTS 4960- Performance Art", + "ARTS 2210 - Sculpture I", + "ARTS 2220 - Fundamentals of 2D Design", + "ARTS 2380 - Music and Sound I", + "ARTS 2700 - Sound Recording and Production I", + "ARTS 2960 - Topics in the Arts Credit Hours 2 to 4(Radical Graphics/Screenprinting)", + "ARTS 4210 - Sculpture II", + "ARTS 4960 - Topics in the Arts Credit Hours 2 to 4(History and Analysis of Western Music)", + "COGS 2120 - Introduction to Cognitive Science", + "COGS 4620 - Cognitive Engineering", + "COMM 2570 - Typography", + "COMM 2660 - Introduction to Graphic Design", + "COMM 4320 - Visual Poetics and Narrative", + "COMM 4460 - Visual Design Theory and Application", + "COMM 4960 - Topics in Communication (Brand Identity Design)", + "PSYC 2220 - Human Factors in Design" + ] + }, + { + "Name": [ + "Electronic Art" + ], + "Choose one of the following": [ + "IHSS 1960 - Behind the Television Screen", + "IHSS 1960 – Remixing in Digital Culture", + "ARTS 1020 - Digital Imaging", + "ARTS 1050 - Art History", + "IHSS 1030 - Behind the TV Screen", + "IHSS 1040 - Documentary in the 21st Century Identity Production" + ], + "Choose remaining credits from the following": [ + "ARTS 4960 Performance Art", + "ARTS 2040 - Intermediate Digital Imaging", + "ARTS 2060 - 2D Experimental Animation", + "ARTS 2070 - Graphic Storytelling", + "ARTS 2230 - 3D Digital Modeling", + "ARTS 2700 - Sound Recording and Production I", + "ARTS 4060 - 3D Visual Effects", + "ARTS 4070 - 3D Animation", + "ARTS 4090 - Art and Code and Interactivity", + "ARTS 4860 - Advanced Digital Imaging" + ], + "Compatible minor(s)": [ + "Electronic Arts Minor" + ] + }, + { + "Name": [ + "Graphic Design" + ], + "Choose 12 credits from the following, with at least 4 credits at the 4000-level": [ + "IHSS 1560 - Media and Society", + "IHSS 1562 - Life in Color", + "COMM 2520 - Communication Theory and Practice", + "COMM 2570 - Typography", + "COMM 2660 - Introduction to Graphic Design", + "COMM 4320 - Visual Poetics and Narrative", + "COMM 4460 - Visual Design Theory and Application", + "COMM 4970 - 2D Motion Graphics", + "COMM 4730 - Brand Identity Design", + "COMM 4690 - Interface Design Hypermedia Theory and Application", + "COMM 4880 - Interactive Data Visualization", + "WRIT 1110 - Writing in Context" + ], + "Compatible minor(s)": [ + "Graphic Design Minor" + ] + }, + { + "Name": [ + "Studio Arts" + ], + "Required": [ + "ARTS 1050 - Art History", + "orARTS 2540 - The Multimedia Century" + ], + "Choose remaining credits from the following": [ + "ARTS 1XXX", + "ARTS 1200 - Basic Drawing", + "ARTS 2200 - Intermediate Drawing", + "ARTS 2210 - Sculpture I", + "ARTS 2220 - Fundamentals of 2D Design", + "ARTS 4200 - Advanced Drawing", + "ARTS 4210 - Sculpture II", + "ARTS 4220 - Painting", + "ARTS 4260 - Life Drawing and Anatomy for Artists" + ], + "Compatible minor(s)": [ + "Studio Arts" + ] + } + ] + }, + { + "Category Name": [ + "Cognitive Science" + ], + "Pathways": [ + { + "Name": [ + "Artificial Intelligence" + ], + "Required": [ + "COGS 2120 - Introduction to Cognitive Science" + ], + "Choose remaining credits from the following": [ + "PHIL 4960 – Ethics of AI", + "COGS 4960 - Learning and Advanced Game AI", + "PHIL 4961 - Intermediate Formal Logic & AI", + "IHSS 1972 - AI and Society", + "IHSS 1140 - Minds and Machines", + "IHSS 1235 - Are Humans Rational?", + "COGS 4210 - Cognitive Modeling", + "COGS 4410 - Programming for Cognitive Science and Artificial Intelligence", + "COGS 4420 - Game AI", + "COGS 4640 - Intelligent Virtual Agents", + "COGS 4880 - Language-Endowed Intelligent Agents" + ], + "Compatible minor(s)": [ + "Cognitive Science of Artificial Intelligence Minor" + ] + }, + { + "Name": [ + "Behavioral and Cognitive Neuroscience" + ], + "Required": [ + "PSYC 1200 - Introduction to Psychological Science" + ], + "Choose remaining credits from the following, with at least 4 credits at the 4000-level": [ + "IHSS 1960 – Understanding Empathy,", + "COGS 4330 - Introduction to Cognitive Neuroscience", + "COGS 4360 - Behavioral Neuroscience", + "COGS 4600 - Cognition and the Brain", + "COGS 4610 - Stress and the Brain", + "COGS 4700 - Hormones, Brain, and Behavior", + "PSYC 4330 - Introduction to Cognitive Neuroscience", + "PSYC 4360 - Behavioral Neuroscience", + "PSYC 4500 - Drugs, Society, and Behavior", + "PSYC 4600 - Cognition and the Brain", + "PSYC 4610 - Stress and the Brain", + "PSYC 4700 - Hormones, Brain, and Behavior" + ], + "Compatible minor(s)": [ + "Behavioral and Cognitive Neuroscience" + ] + }, + { + "Name": [ + "Linguistics" + ], + "Required": [ + "COGS 2340 - Introduction to Linguistics" + ], + "Choose 4 credits from the following": [ + "LANG 1XXX", + "LANG 2XXX" + ], + "Choose remaining credits from the following, with at least 4 credits at the 4000-level": [ + "LANG 4XXX", + "IHSS 1492 - Language and Culture", + "COGS 4340 - The Linguistics of Computational Linguistics", + "COGS 4560 - Cross-linguistic Perspectives", + "COGS 4780 - Advanced Topics in Linguistics", + "COGS 4880 - Language-Endowed Intelligent Agents" + ], + "Compatible minor(s)": [ + "Linguistics Minor" + ] + }, + { + "Name": [ + "Mind, Brain, and Intelligence" + ], + "Required": [ + "COGS 2120 - Introduction to Cognitive Science" + ], + "Choose remaining credits from the following": [ + "IHSS 1140 - Minds and Machines", + "IHSS 1235 - Are Humans Rational?", + "IHSS 1972 AI & Society", + "COGS 4330 - Introduction to Cognitive Neuroscience", + "COGS 4600 - Cognition and the Brain", + "PSYC 4350 - Mathematical Methods in Psychological Science", + "PSYC 4370 - Cognitive Psychology", + "PSYC 4410 - Sensation and Perception", + "PHIL 4961 - Intermediate Formal Logic & AI" + ], + "4000-level COGS ElectiveCompatible minor(s)": [ + "Cognitive Science Minor" + ] + }, + { + "Name": [ + "Understanding Human Behavior" + ], + "Required": [ + "PSYC 1200 - Introduction to Psychological Science" + ], + "Choose remaining credits from the following, with at least 4 credits at the 4000 level": [ + "IHSS 19XX – Understanding Empathy", + "PSYC 2XXX", + "PSYC 4XXX", + "PSYC 2310 - Research Methods and Statistics I", + "PSYC 2730 - Social Psychology", + "PSYC 2800 - Introduction to Sports Psychology", + "PSYC 4110 - Motivation and Performance", + "PSYC 4200 - Industrial and Organizational Psychology", + "PSYC 4310 - Research Methods and Statistics II", + "PSYC 4350 - Mathematical Methods in Psychological Science", + "PSYC 4370 - Cognitive Psychology", + "PSYC 4400 - Personality", + "PSYC 4450 - Learning", + "PSYC 4500 - Drugs, Society, and Behavior", + "PSYC 4720 - Abnormal Psychology", + "PSYC 4740 - Psychology and The Law", + "PSYC 4750 - Forensic Psychology", + "PSYC 4800 - Sport Psychology Seminar" + ], + "Compatible minor(s)": [ + "General Psychology Minor and Psychological Science Minor" + ] + }, + { + "Name": [ + "Well-being: Body and Mind" + ], + "Choose one of the following": [ + "IHSS 19XX – Understanding Empathy", + "ARTS 1200 - Basic Drawing", + "IHSS 1110 - Nature/Society", + "IHSS 1140 - Minds and Machines", + "IHSS 1175 - Well-being Cultivating Curiosity", + "IHSS 1180 - The Art of Listening", + "IHSS 1700 - Songwriting Workshop", + "IHSS 1720 - Music and Nature" + ], + "Choose remaining credits from the following, with at least 4 credits at the 4000 level": [ + "ARTS 2310 - Rensselaer Concert Choir Credit Hours 1 (course can be repeated multiple times for credit)", + "ARTS 2960 - Topics in the Arts Credit Hours 2 to 4(Private Lessons, Credit Hours 1)", + "COGS 4610 - Stress and the Brain", + "COGS 4700 - Hormones, Brain, and Behavior", + "PHIL 4240 - Ethics", + "PSYC 1200 - Introduction to Psychological Science", + "PSYC 4430 - Psychology of Mindfulness", + "PSYC 4440 - Sensibilities", + "PSYC 4500 - Drugs, Society, and Behavior", + "PSYC 4610 - Stress and the Brain", + "PSYC 4700 - Hormones, Brain, and Behavior", + "PSYC 4730 - Positive Psychology", + "PSYC 4960 - Topics in Psychology Credit Hours 1 to 4(Empathy and Emotion)", + "WRIT 2320 - Creative Writing Creative Non-Fiction", + "WRIT 2330 - Creative Writing The Short Story" + ], + "Compatible minor(s)": [ + "Well-being" + ] + } + ] + }, + { + "Category Name": [ + "Communication/ Writing" + ], + "Pathways": [ + { + "Name": [ + "Fact and Fiction" + ], + "Choose one of the following": [ + "IHSS 1976 – Fiction from Film to the Internet IHSS 1964 - Documentary in the 21st Century ARTS 1030 - Digital Filmmaking", + "IHSS 1160 - Science and Scientific Misconduct", + "IHSS 1300 - Race and Film in U.S. Culture and History", + "IHSS 1560 - Media and Society", + "PHIL 1110 - Introduction to Philosophy", + "IHSS 1550 - Fiction From Film to the Internet", + "IHSS 1776 - The American Dream Credit Hours" + ], + "Choose remaining credits from the following": [ + "ARTS 4040 - Rethinking Documentary Video Production", + "ARTS 4560 - Hactivism", + "ARTS 4640 - Science Fictions", + "COMM 2440 - Documentary Film", + "COMM 4530 - Reality TV and Post-Factual Media", + "COMM 4580 - Advertising and Culture", + "LITR 4150 - Science and Fiction", + "PHIL 2100 - Critical Thinking", + "PHIL 4130 - Philosophy of Science", + "PSYC 2100 - Critical Thinking", + "STSO 4430 - Drugs in History", + "STSO 4590 - American Politics in Crisis", + "WRIT 2320 - Creative Writing Creative Non-Fiction", + "WRIT 2330 - Creative Writing The Short Story" + ] + }, + { + "Name": [ + "Literature and Creative Writing" + ], + "Choose 12 credits from the following, at least 4 credits at the 4000 level": [ + "LITR XXXX", + "WRIT 1XXX", + "WRIT 2XXX", + "IHSS 1550 - Fiction From Film to the Internet", + "IHSS 1776 - The American Dream Credit Hours", + "COMM 4320 - Visual Poetics and Narrative", + "COMM 4780 - Interactive Narrative", + "LITR 2110 - Introduction to Literature", + "LITR 2150 - Modern and Contemporary Literature", + "LITR 4150 - Science and Fiction", + "LITR 4230 - Irish Literature", + "LITR 4770 - Women Writers", + "WRIT 1110 - Writing in Context", + "WRIT 2320 - Creative Writing Creative Non-Fiction", + "WRIT 2330 - Creative Writing The Short Story" + ], + "Compatible minor(s)": [ + "Literature and Creative Writing Minor" + ] + }, + { + "Name": [ + "Strategic Communication" + ], + "Choose 12 credits of the following, with at least 4 credits at the 4000 level": [ + "COMM 1XXX", + "COMM 2XXX", + "IHSS 19XX – Writing and Society", + "WRIT 4XXX", + "COMM 2520 - Communication Theory and Practice", + "COMM 2660 - Introduction to Graphic Design", + "COMM 4580 - Advertising and Culture", + "IHSS 1492 - Language and Culture", + "IHSS 1560 - Media and Society", + "WRIT 1110 - Writing in Context", + "WRIT 2110 - Strategic Writing", + "WRIT 2340 - Speech Communication" + ], + "Compatible minor(s)": [ + "Strategic Communication Minor" + ] + } + ] + }, + { + "Category Name": [ + "Ecology" + ], + "Pathways": [ + { + "Name": [ + "Environmental Future" + ], + "Choose one of the following": [ + "IHSS 1960 – Music and Protest", + "IHSS 1960 – Designing Climate Justice", + "IHSS 1110 - Nature/Society", + "IHSS 1200 - Principles of Economics", + "IHSS 1240 - Sustainability Debates", + "IHSS 1320 - A Century of Environmental Thought", + "IHSS 1350 - Law, Values, and Public Policy Perspectives on Science and Technology", + "IHSS 1720 - Music and Nature", + "IHSS 1040 - Documentary in the 21st Century Identity Production" + ], + "Choose remaining credits from the following": [ + "ARTS 4250 - Art, Community, and Technology", + "ARTS 4240 - Eco Chic Living Art", + "ECON 4230 - Environmental Economics", + "PHIL 4300 - Environmental Philosophy", + "PHIL 4500 - Bioethics", + "STSO 4250 - Bioethics", + "STSO 4720 - Consumer Culture", + "STSO 4280 - Sustainability Education", + "ARTS 4120 - Biopunk Arts Lab Practice", + "ARTS 4140 - Queer Ecologies" + ] + }, + { + "Name": [ + "Sustainability" + ], + "Required": [ + "STSO 2300 - Environment and Society" + ], + "Choose remaining credits from the following must complete at least 4 credits at the 4000-level": [ + "IHSS 1960 - Designing Climate Justice", + "STSO 1110 - Science, Technology, and Society", + "IHSS 1110 - Nature/Society", + "IHSS 1320 - A Century of Environmental Thought", + "IHSS 1240 - Sustainability Debates", + "STSO 4300 - Sustainability and STS Sustainability Careers", + "STSO 4340 - Environmental Philosophy", + "STSO 4510 - History of American Technology", + "STSO 4720 - Consumer Culture", + "STSO 4260 - Food, Farms, and Famine", + "STSO 4280 - Sustainability Education", + "STSO 4350 - Politics of Design", + "STSO 4500 - Globalization and Development", + "STSO 4330 - Environmental Justice" + ], + "Compatible minor(s)": [ + "Sustainability Studies Minor" + ] + } + ] + }, + { + "Category Name": [ + "Economics" + ], + "Pathways": [ + { + "Name": [ + "Economics" + ], + "Choose one of the following": [ + "ECON 1200 - Introductory Economics", + "IHSS 1200 - Principles of Economics" + ], + "Choose other one of the following": [ + "ECON 2XXX", + "ECON 2010 - Intermediate Microeconomic Theory", + "ECON 2020 - Intermediate Macroeconomic Theory" + ], + "Choose remaining credits from": [ + "ECON 4XXX" + ], + "Compatible minor(s)": [ + "Economics Minor" + ] + }, + { + "Name": [ + "Economics of Banking and Finance" + ], + "Required": [ + "ECON 4130 - Money and Banking", + "ECON 4330 - Economics of Financial Institutions and Markets" + ], + "Choose one of the following": [ + "ECON 1200 - Introductory Economics", + "IHSS 1200 - Principles of Economics" + ], + "Compatible minor(s)": [ + "Economics of Banking and Finance Minor" + ] + }, + { + "Name": [ + "Economics of Decision-Making" + ], + "Choose of of the following": [ + "IHSS 1200 - Principles of Economics", + "ECON 1200 - Introductory Economics" + ], + "Remaining credits from the following": [ + "ECON 4220 - Applied Game Theory", + "ECON 4270 - Behavioral Economics", + "ECON 4340 - Behavioral Financial Economics", + "ECON 4320 - Economic Models of Decision-Making", + "ECON 4360 - Experimental Economics" + ] + }, + { + "Name": [ + "Economics of Healthcare Market" + ], + "Choose one of the following": [ + "ECON 1200 - Introductory Economics", + "IHSS 1200 - Principles of Economics" + ], + "Choose remaining credits from the following": [ + "ECON 4170 - Health Economics and Policy", + "ECON 4270 - Behavioral Economics", + "ECON 4290 - Economics of Biotech and Medical Innovations" + ], + "Compatible minor(s)": [ + "Economics of Healthcare Markets" + ] + }, + { + "Name": [ + "Economics of Policy and Regulation" + ], + "Choose one of the following": [ + "ECON 1200 - Introductory Economics", + "IHSS 1200 - Principles of Economics" + ], + "Choose remaining credits from the following": [ + "ECON 4150 - Economics of Government Regulation and Firm Strategy", + "ECON 4170 - Health Economics and Policy", + "ECON 4310 - Law and Economics", + "ECON 4230 - Environmental Economics" + ], + "Compatible minor(s)": [ + "Economics of Policy and Regulations" + ] + }, + { + "Name": [ + "Economics of Quantitative Modeling" + ], + "Choose one of the following": [ + "ECON 1200 - Introductory Economics", + "IHSS 1200 - Principles of Economics" + ], + "Choose remaining credits from the following": [ + "ECON 4280 - Econometric Methods for Big Data", + "ECON 4570 - Econometrics", + "ECON 4360 - Experimental Economics" + ], + "Compatible minor(s)": [ + "Economics of Quantitative Modeling" + ] + }, + { + "Name": [ + "Economics of Technology and Innovation" + ], + "Choose one of the following": [ + "ECON 1200 - Introductory Economics", + "IHSS 1200 - Principles of Economics" + ], + "Choose remaining credits from the following": [ + "ECON 4110 - Economics of Innovation and New Technologies", + "ECON 4290 - Economics of Biotech and Medical Innovations", + "ECON 4430 - Economics of Growth & Innovation" + ], + "Compatible minor(s)": [ + "Economics of Technology and Innovation Minor" + ] + } + ] + }, + { + "Category Name": [ + "Information Technology" + ], + "Pathways": [ + { + "Name": [ + "Information Technology and Web Sciences" + ], + "Required": [ + "ITWS 2210 - Introduction to Human Computer Interaction" + ], + "Choose One of the following": [ + "IHSS 1220 - IT and Society", + "ITWS 1220 - IT and Society" + ], + "Choose remaining credits from the following": [ + "ARTS 2540 - The Multimedia Century", + "COGS 2120 - Introduction to Cognitive Science", + "COMM 2520 - Communication Theory and Practice", + "COMM 2660 - Introduction to Graphic Design", + "IHSS 1200 - Principles of Economics", + "PHIL 2100 - Critical Thinking", + "PHIL 2140 - Introduction to Logic", + "PSYC 1200 - Introduction to Psychological Science", + "STSO 1110 - Science, Technology, and Society", + "STSO 2210 - Design, Culture, and Society", + "WRIT 2110 - Strategic Writing", + "WRIT 2340 - Speech Communication", + "COMM 4420 - Foundations of HCI Usability" + ] + }, + { + "Name": [ + "Interactive Media/Data Design" + ], + "Choose 12 credits from the following, with at least 4 credits at the 4000 level": [ + "IHSS 1560 - Media and Society", + "WRIT 1110 - Writing in Context", + "COMM 2520 - Communication Theory and Practice", + "COMM 2660 - Introduction to Graphic Design", + "COMM 4420 - Foundations of HCI Usability", + "COMM 4470 - Information Design", + "COMM 4690 - Interface Design Hypermedia Theory and Application", + "COMM 4780 - Interactive Narrative", + "COMM 4880 - Interactive Data Visualization" + ], + "Compatible minor(s)": [ + "Graphic Design Minor" + ] + }, + { + "Name": [ + "Living in a World of Data" + ], + "Choose remaining credits from the following": [ + "IHSS 1140 - Minds and Machines", + "IHSS 1150 - The Genome and You", + "IHSS 1160 - Science and Scientific Misconduct", + "IHSS 1200 - Principles of Economics", + "ITWS 1220 - IT and Society", + "IHSS 1220 - IT and Society", + "COMM 4470 - Information Design", + "COMM 4690 - Interface Design Hypermedia Theory and Application", + "COMM 4880 - Interactive Data Visualization", + "ECON 4220 - Applied Game Theory", + "ECON 4270 - Behavioral Economics", + "ECON 4570 - Econometrics", + "PHIL 2100 - Critical Thinking", + "PSYC 2100 - Critical Thinking", + "PSYC 2310 - Research Methods and Statistics I", + "PSYC 4350 - Mathematical Methods in Psychological Science" + ] + } + ] + }, + { + "Category Name": [ + "Language" + ], + "Pathways": [ + { + "Name": [ + "Chinese Language" + ], + "Choose 12 credits from the following": [ + "LANG 1410 - Chinese I", + "LANG 2410 - Chinese II", + "LANG 4420 - Chinese III", + "LANG 4430 - Chinese IV", + "LANG 4470 - Chinese V" + ], + "Compatible minor(s)": [ + "Chinese Language Minor" + ] + }, + { + "Name": [ + "Foreign Language" + ], + "Choose 12 credits from the following, with at least 8 credit hours at, or above, the 2000-level and at least 3 credit hours at the 4000-level": [ + "LANG 1XXX", + "LANG 2XXX", + "LANG 4XXX" + ] + } + ] + }, + { + "Category Name": [ + "Media / Music" + ], + "Pathways": [ + { + "Name": [ + "Game Studies" + ], + "Choose 12 credits from the following": [ + "GSAS 1600 - History and Culture of Games", + "GSAS 2510 - Introduction to Game Design", + "GSAS 2520 - Introduction to Game Storytelling", + "GSAS 2540 - Introduction to Game Programming", + "GSAS 4520 - Game Development I", + "GSAS 4540 - Game Development II", + "GSAS 4510 - Experimental Game Design" + ] + }, + { + "Name": [ + "Media and Culture" + ], + "Choose 12 credits from the following, with at least 4 credits at the 4000-level": [ + "IHSS 19XX – Remixing in Digital Culture", + "IHSS 19XX – Technology and the Top Ten", + "COMM 29XX - The Film Experience", + "IHSS 1030 - Behind the TV Screen", + "IHSS 1560 - Media and Society", + "IHSS 1776 - The American Dream Credit Hours", + "COMM 2410 - Perspectives on Photography", + "COMM 2440 - Documentary Film", + "COMM 2520 - Communication Theory and Practice", + "COMM 2616 - Superheroes in the Classroom", + "COMM 2750 - Critical Television", + "COMM 4530 - Reality TV and Post-Factual Media", + "COMM 4540 - Visual Culture", + "COMM 4550 - Religion in the Media", + "COMM 4580 - Advertising and Culture", + "ARTS 4040 - Rethinking Documentary Video Production" + ], + "Compatible minor(s)": [ + "Media and Culture Minor" + ] + }, + { + "Name": [ + "Music and Culture" + ], + "Choose one of the following": [ + "IHSS 19XX – Remixing in Digital Culture", + "IHSS 19XX - Technology and the Top 10", + "IHSS 1010 - Exploring Music @Rensselaer", + "ARTS 2510 - Histories of Jazz and Improvised Music", + "IHSS 1700 - Songwriting Workshop", + "ARTS 2550 - Popular Music and Society" + ], + "Choose remaining credits from the following": [ + "ARTS 4960 - Performance Art", + "ARTS 2520 - World Music", + "ARTS 2700 - Sound Recording and Production I", + "ARTS 4700 - Sound Recording and Production II", + "ARTS 2500 - Histories of Western Music", + "ARTS 2180 - Deep Listening", + "ARTS 4180 - Topics in Deep Listening" + ], + "Compatible minor(s)": [ + "Music Minor" + ] + }, + { + "Name": [ + "Music Composition and Production" + ], + "Choose one of the following": [ + "IHSS 19XX – Remixing in Digital Culture", + "IHSS 19XX – Technology and the Top Ten", + "ARTS 1380 - Fundamentals of Music and Sound", + "IHSS 1010 - Exploring Music @Rensselaer", + "ARTS 2510 - Histories of Jazz and Improvised Music", + "IHSS 1700 - Songwriting Workshop", + "ARTS 2550 - Popular Music and Society", + "ARTS 2500 - Histories of Western Music" + ], + "Choose remaining credits from the following": [ + "ARTS 2020 - Music and Technology I", + "ARTS 2380 - Music and Sound I", + "ARTS 2600 - Ensemble Nonlinear Credit Hours", + "1ARTS 2700 - Sound Recording and Production I", + "ARTS 4160 - Music and Technology II", + "ARTS 4380 - Music and Sound II", + "ARTS 4700 - Sound Recording and Production II" + ], + "Compatible minor(s)": [ + "Music Minor" + ] + }, + { + "Name": [ + "Music Performance" + ], + "Choose one of the following": [ + "IHSS 19XX – Remixing in Digital Culture", + "ARTS 1380 - Fundamentals of Music and Sound", + "IHSS 1010 - Exploring Music @Rensselaer", + "ARTS 2510 - Histories of Jazz and Improvised Music", + "ARTS 2550 - Popular Music and Society", + "ARTS 2500 - Histories of Western Music" + ], + "Choose remaining credits from the following": [ + "ARTS 2180 - Deep Listening", + "ARTS 2300 - Rensselaer Orchestra Credit Hours 1 (course can be repeated multiple times for credit)", + "ARTS 2310 - Rensselaer Concert Choir Credit Hours 1 (course can be repeated multiple times for credit)", + "ARTS 2350 - Chamber Music Ensemble Credit Hours 1 (course can be repeated multiple times for additional credit)", + "ARTS 2600 - Ensemble Nonlinear Credit Hours", + "ARTS 2960 - Topics in the Arts Credit Hours 2 to 4(Fusion Ensemble or Contemporary Improv Ensemble )", + "ARTS 4180 - Topics in Deep Listening", + "ARTS 2750 - Private Music Lessons Credit Hours 1 (course can be repeated multiple times for credit)" + ], + "Compatible minor(s)": [ + "Music Minor" + ] + }, + { + "Name": [ + "Video, Performance, and Social Practice" + ], + "Choose one of the following": [ + "IHSS 19XX – Remixing in Digital Culture", + "IHSS 19XX – Technology and the Top Ten", + "ARTS 1030 - Digital Filmmaking", + "IHSS 1300 - Race and Film in U.S. Culture and History", + "IHSS 1030 - Behind the TV Screen", + "IHSS 1180 - The Art of Listening", + "IHSS 1040 - Documentary in the 21st Century Identity Production" + ], + "Choose remaining credits from the following, with at least 4 credits at the 4000 level": [ + "ARTS 2010 - Intermediate Video", + "ARTS 2540 - The Multimedia Century", + "ARTS 4040 - Rethinking Documentary Video Production", + "ARTS 4250 - Art, Community, and Technology", + "ARTS 4130 - New Media Theory", + "ARTS 4240 - Eco Chic Living Art", + "ARTS 4560 - Hactivism", + "ARTS 4630 - Writing and Directing for Video", + "ARTS 4640 - Science Fictions", + "ARTS 4120 - Biopunk Arts Lab Practice", + "ARTS 4140 - Queer Ecologies", + "ARTS 4050 - Advanced Video Media Studio" + ], + "Compatible minor(s)": [ + "Video, Performance, and Social Practice Electronic Arts Minor" + ] + } + ] + }, + { + "Category Name": [ + "Philosophy" + ], + "Pathways": [ + { + "Name": [ + "Extent and Limits of Rationality" + ], + "Select 12 credits from the following": [ + "IHSS 1140 - Minds and Machines", + "IHSS 1180 - The Art of Listening", + "IHSS 1200 - Principles of Economics", + "IHSS 1235 - Are Humans Rational?", + "IHSS 1570 - War and Technolog Past, Present, and Future", + "IHSS 1510 - War and Society", + "COGS 2120 - Introduction to Cognitive Science", + "COMM 2520 - Communication Theory and Practice", + "ECON 4220 - Applied Game Theory", + "ECON 4270 - Behavioral Economics", + "PHIL 2100 - Critical Thinking", + "PHIL 2140 - Introduction to Logic", + "PSYC 2100 - Critical Thinking", + "PSYC 4370 - Cognitive Psychology", + "STSO 4530 - History of Science and Technology", + "WRIT 2340 - Speech Communication", + "WRIT 4550 - Proposing and Persuading", + "PHIL 4961 – Intermediate Formal Logic & AI" + ] + }, + { + "Name": [ + "Logical Thinking" + ], + "Choose 12 credits from a choice of the following, with at least 4 credits at the 4000-level": [ + "IHSS 1140 - Minds and Machines", + "IHSS 1235 - Are Humans Rational?", + "PSYC 2100 - Critical Thinking", + "PHIL 2100 - Critical Thinking", + "PHIL 2140 - Introduction to Logic", + "PHIL 4140 - Intermediate Logic", + "PHIL 4420 - Computability and Logic", + "PHIL 4960 – Inductive Logic", + "PHIL 4961 – Intermediate Formal Logic & AI" + ], + "Compatible minor(s)": [ + "Philosophy of Logic, Computation, and Mind Minor" + ] + }, + { + "Name": [ + "Philosophy" + ], + "Choose one of the following": [ + "PHIL1000", + "IHSS 19XX Philosophy, Technology, and the Human Future", + "IHSS 1150 - The Genome and You", + "IHSS 1160 - Science and Scientific Misconduct", + "IHSS 1165 - Great Ideas in Philosophy", + "PHIL 1110 - Introduction to Philosophy", + "PHIL 2100 - Critical Thinking", + "PHIL 2140 - Introduction to Logic", + "PSYC 2100 - Critical Thinking" + ], + "Choose remaining credits from the following with at least 4 credits at the 4000-level": [ + "PHIL 2XXX", + "PHIL 4XXX", + "PHIL 2100 - Critical Thinking", + "PHIL 2140 - Introduction to Logic", + "PHIL 2400 - Philosophy of Biology", + "PHIL 4130 - Philosophy of Science", + "PHIL 4240 - Ethics", + "PHIL 4300 - Environmental Philosophy", + "PHIL 4480 - Metaphysics and Consciousness", + "PSYC 2100 - Critical Thinking" + ], + "Compatible minor(s)": [ + "Philosophy Minor" + ] + }, + { + "Name": [ + "Thinking with Science" + ], + "Choose 12 credits from the following": [ + "IHSS 1160 - Science and Scientific Misconduct", + "IHSS 1175 - Well-being Cultivating Curiosity", + "IHSS 1570 - War and Technology Past, Present, and Future", + "STSO 1110 - Science, Technology, and Society", + "ARTS 4240 - Eco Chic Living Art", + "ARTS 4960 - Topics in the Arts Credit Hours 2 to 4(Bio-Punk) Arts Lab Practices)", + "COMM 2520 - Communication Theory and Practice", + "LITR 4150 - Science and Fiction", + "PHIL 2100 - Critical Thinking", + "PHIL 2400 - Philosophy of Biology", + "PHIL 4130 - Philosophy of Science", + "PSYC 2100 - Critical Thinking", + "STSO 4510 - History of American Technology", + "STSO 4530 - History of Science and Technology", + "STSO 4400 - Medicine, Culture, and Society", + "WRIT 2110 - Strategic Writing", + "WRIT 4410 - Research Writing", + "WRIT 4550 - Proposing and Persuading" + ] + } + ] + }, + { + "Category Name": [ + "Social Science" + ], + "Pathways": [ + { + "Name": [ + "Art History, Theory, and Criticits" + ], + "Choose one of the following": [ + "ARTS 1050 - Art History", + "ARTS 2510 - Histories of Jazz and Improvised Music", + "IHSS 1170 - History of Animation", + "IHSS 1300 - Race and Film in U.S. Culture and History", + "IHSS 1700 - Songwriting Workshop" + ], + "Choose remaining credits from the following": [ + "ARTS 2540 - The Multimedia Century", + "ARTS 4130 - New Media Theory", + "ARTS 2500 - Histories of Western Music" + ] + }, + { + "Name": [ + "Design, Innovation, and Society" + ], + "Required": [ + "IHSS 1610 - Design and Innovation Studio I", + "STSO 2610 - Design and Innovation Studio II" + ], + "Choose remaining credits from the following": [ + "ENGR 4610 - Design and Innovation Studio C", + "STSO 4605 - Design and Innovation Studio B", + "STSO 4610 - Design and Innovation Studio C" + ] + }, + { + "Name": [ + "Ethics, Integrity, and Social Responsibility" + ], + "Choose 12 credits from the following": [ + "IHSS 1140 - Minds and Machines", + "IHSS 1150 - The Genome and You", + "IHSS 1160 - Science and Scientific Misconduct", + "IHSS 1350 - Law, Values, and Public Policy Perspectives on Science and Technology", + "STSO 1110 - Science, Technology, and Society", + "IHSS 1960 – Designing Climate Justice", + "ARTS 4250 - Art, Community, and Technology", + "ARTS 4240 - Eco Chic Living Art", + "ARTS 4560 - Hactivism", + "PHIL 4240 - Ethics", + "PHIL 4300 - Environmental Philosophy", + "PHIL 4500 - Bioethics", + "STSO 4210 - Engineering Ethics", + "STSO 4250 - Bioethics", + "STSO 4340 - Environmental Philosophy", + "STSO 4400 - Medicine, Culture, and Society" + ] + }, + { + "Name": [ + "Gender, Race, Sexuality, Ethnicity, and Social Change" + ], + "Choose 12 credits from the following": [ + "COMM 2440 - Documentary Film", + "COMM 4550 - Religion in the Media", + "LITR 4770 - Women Writers", + "STSO 2510 - Cultural Anthropology", + "STSO 2520 - Sociology", + "STSO 4560 - Gender, Science, and Technology", + "ARTS 4140 - Queer Ecologies", + "ARTS 2550 - Popular Music and Society" + ], + "Can select only one of the following to be applied to pathway": [ + "IHSS 1968 – Songs of Identity", + "IHSS 19XX – Revolutions in Perspective", + "IHSS 19XX - Worlds on Display", + "IHSS 1150 - The Genome and You", + "IHSS 1300 - Race and Film in U.S. Culture and History", + "IHSS 1492 - Language and Culture", + "IHSS 1560 - Media and Society", + "IHSS 1666 - Religion in a Global World" + ] + }, + { + "Name": [ + "History" + ], + "Required": [ + "STSO 2500 - American History" + ], + "Choose remaining credits from the following": [ + "STSO 4000 – STS Elective IHSS 1960 - Revolutions in Perspective", + "STSO 1110 - Science, Technology, and Society", + "IHSS 1776 - The American Dream Credit Hours", + "IHSS 1570 - War and Technology Past, Present, and Future", + "IHSS 1320 - A Century of Environmental Thought", + "STSO 4420 - History of Medicine", + "STSO 4430 - Drugs in History", + "STSO 4440 - History of Mental Health", + "STSO 4510 - History of American Technology", + "STSO 4530 - History of Science and Technology", + "STSO 4720 - Consumer Culture" + ], + "Compatible minor(s)": [ + "History Minor" + ] + }, + { + "Name": [ + "Law and Policy" + ], + "Required": [ + "STSS 2700 - Law and Society" + ], + "Choose one of the following": [ + "IHSS 19XX – Revolutions in Comparative Perspective", + "IHSS 19XX – Sociology of Inequality", + "IHSS 1350 - Law, Values, and Public Policy: Perspectives on Science and Technology", + "IHSS 1500 - Human Rights in History", + "IHSS 1510 - War and Society", + "STSH 1110 - Science, Technology, and Society", + "STSS 1110 - Science, Technology, and Society" + + ], + "Choose remaining credits from the following": [ + "STSH 4210 - Engineering Ethics", + "STSH 4310 - Energy Politics", + "STSH 4430 - Drugs in History", + "STSH 4520 - Social Demography: Society by the Numbers", + "STSH 4700 - Environmental Law", + "STSH 4800 - Public Service and Social Justice", + "STSS 4310 - Energy Politics", + "STSS 4320 - Resilience Planning", + "STSS 4430 - Drugs in History", + "STSS 4520 - Social Demography: Society by the Numbers", + "STSS 4540 - China and the United States", + "STSS 4560 - Gender, Science, and Technology", + "STSS 4570 - Contemporary Political Thought", + "STSS 4590 - American Politics in Crisis", + "STSS 4800 - Public Service and Social Justice" + ], + "Compatible minor(s)": [ + "Law and Policy Minor" + ] + }, + { + "Name": [ + "Public Health" + ], + "Required": [ + "STSO 2520 - Sociology" + ], + "Choose one of the following": [ + "IHSS 1150 - The Genome and You", + "PSYC 1200 - Introduction to Psychological Science", + "STSO 1110 - Science, Technology, and Society" + ], + "Choose remaining credits from the following": [ + "COGS 4610 - Stress and the Brain", + "COGS 4700 - Hormones, Brain, and Behavior", + "PSYC 4500 - Drugs, Society, and Behavior", + "PSYC 4610 - Stress and the Brain", + "PSYC 4700 - Hormones, Brain, and Behavior", + "STSO 4420 - History of Medicine", + "STSO 4440 - History of Mental Health", + "STSO 4250 - Bioethics", + "STSO 4430 - Drugs in History", + "STSO 4260 - Food, Farms, and Famine", + "STSO 4400 - Medicine, Culture, and Society", + "STSO 4560 - Gender, Science, and Technology" + ], + "Compatible minor(s)": [ + "Public Health Minor" + ] + }, + { + "Name": [ + "Science, Technology, and Society" + ], + "Choose one of the following a minimum of 4 credits must be completed at the 4000-level": [ + "STSO 4XXX", + "STSO 1110 - Science, Technology, and Society", + "ITWS 1220 - IT and Society", + "IHSS 1220 - IT and Society", + "STSO 2500 - American History", + "STSO 2300 - Environment and Society", + "STSO 2510 - Cultural Anthropology", + "STSO 2520 - Sociology" + ], + "Compatible minor(s)": [ + "Science, Technology, and Society Minor" + ] + } + ] + }, + { + "Category Name": [ + "Transfer Student" + ], + "Pathways": [ + { + "Name": [ + "Transfer Student Arts and Humanitity" + ], + "Choose 12 credits of the following course prefixes, with at least 8 credit hours at, or above, the 2000 level and at least 3 credit hours at the 4000 level": [ + "ARTS XXXX", + "COMM XXXX", + "GSAS XXXX", + "IHSS XXXX", + "LANG XXXX", + "LITR XXXX", + "PHIL XXXX", + "STSH XXXX", + "WRIT XXXX" + ] + }, + { + "Name": [ + "Transfer Student Social Sciece" + ], + "Choose 12 credits of the following course prefixes, with at least 8 credit hours at, or above, the 2000 level and at least 3 credit hours at the 4000 level": [ + "COGS XXXX", + "ECON XXXX", + "GSAS XXXX", + "IHSS XXXX", + "PSYC XXXX", + "STSS XXXX" + ] + } + ] + } +] \ No newline at end of file diff --git a/scripts/dev-create-migration.sh b/scripts/dev-create-migration.sh old mode 100644 new mode 100755 diff --git a/src/api/app.py b/src/api/app.py index 4ea455c9e..31cf7fe4a 100644 --- a/src/api/app.py +++ b/src/api/app.py @@ -47,7 +47,7 @@ admin_info = AdminInfo.Admin(db_conn) course_select = CourseSelect.student_course_selection(db_conn) semester_info = SemesterInfo.semester_info(db_conn) -professor_info = All_professors.Professor(db_conn, FastAPICache) +professor_info = All_professors.Professor(db_conn, FastAPICache) users = UserModel.User() def is_admin_user(session): @@ -153,6 +153,7 @@ async def uploadHandler( isPubliclyVisible: str = Form(...), file: UploadFile = File(...)): # check for user files + print("in process") if not file: return Response("No file received", 400) if file.filename.find('.') == -1 or file.filename.rsplit('.', 1)[1].lower() != 'csv': @@ -179,6 +180,40 @@ async def uploadHandler( print(error) return Response(error.__str__(), status_code=500) +@app.post('/api/bulkProfessorUpload') +async def uploadJSON( + isPubliclyVisible: str = Form(...), + file: UploadFile = File(...)): + # Check to make sure the user has sent a file + if not file: + return Response("No file received", 400) + + # Check that we receive a JSON file + if file.filename.find('.') == -1 or file.filename.rsplit('.', 1)[1].lower() != 'json': + return Response("File must have JSON extension", 400) + + # Get file contents + contents = await file.read() + + # Load JSON data + try: + #convert string to python dict + json_data = json.loads(contents.decode('utf-8')) + # print(json_data) + except json.JSONDecodeError as e: + return Response(f"Invalid JSON data: {str(e)}", 400) + + # Call populate_from_json method + isSuccess, error = professor_info.populate_from_json(json_data) + if isSuccess: + print("SUCCESS") + return Response(status_code=200) + else: + print("NOT WORKING") + print(error) + return Response(error.__str__(), status_code=500) + + @app.post('/api/mapDateRangeToSemesterPart') async def map_date_range_to_semester_part_handler(request: Request): # This depends on date_start, date_end, and semester_part_name being @@ -299,20 +334,12 @@ async def get_all_professors(): db_list = [dict(prof) for prof in professors] if professors else [] return db_list if not error else Response(error, status_code = 500) -@app.get('/api/professor/office_hours/{email}') -async def get_office_hours(email: str): - professor_office_hours, error = professor_info.get_office_hours_by_email(email) - return professor_office_hours if not error else Response(content=error, status_code=500) - @app.get('/api/professor/phone_number/{email}') async def get_professor_phone_number_by_email(email: str): + phone_number, error = professor_info.get_professor_phone_number_by_email(email) return phone_number if not error else Response(content=error, status_code=500) -@app.get('/api/professor/rcs/{rcs}') -async def get_professor_info_by_rcs(rcs:str): - professor_rcs, error = professor_info.get_professor_info_by_rcs(rcs) - return professor_rcs if not error else Response(content=error,status_code=500) @app.get('/api/professor/email/{email}') async def get_professor_info_by_email(email:str): @@ -355,22 +382,3 @@ async def remove_professor(email:str): print(email) professor, error = professor_info.remove_professor(email) return professor if not error else Response(str(error), status_code=500) - -#Parses the data from the .csv data files -@app.post('/api/bulkProfUpload') -async def uploadHandler(file: UploadFile = File(...)): - # check for user files - if not file: - return Response("No file received", 400) - if file.filename.find('.') == -1 or file.filename.rsplit('.', 1)[1].lower() != 'csv': - return Response("File must have csv extension", 400) - # get file - contents = await file.read() - csv_file = StringIO(contents.decode()) - isSuccess, error = courses.populate_from_csv(csv_file) - # Populate DB from CSV - if (isSuccess): - return Response(status_code=200) - else: - print(error) - return Response(error.__str__(), status_code=500) diff --git a/src/api/db/courses.py b/src/api/db/courses.py index e56fdabb5..89a4363bb 100644 --- a/src/api/db/courses.py +++ b/src/api/db/courses.py @@ -53,6 +53,7 @@ def bulk_delete(self, semesters): for semester in semesters: _, error = self.delete_by_semester(semester) if error: + print("ERROR") print(error) return error # on success, invalidate cache diff --git a/src/api/db/professor.py b/src/api/db/professor.py index 8b964f6e3..c7e554bb9 100644 --- a/src/api/db/professor.py +++ b/src/api/db/professor.py @@ -1,10 +1,6 @@ -import csv import json from psycopg2.extras import RealDictCursor import asyncio -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker -# from your_module import Professor, Base # https://stackoverflow.com/questions/54839933/importerror-with-from-import-x-on-simple-python-files if __name__ == "__main__": @@ -13,121 +9,133 @@ from . import connection class Professor: + def __init__(self, db_conn, cache): self.db_conn = db_conn self.cache = cache - def add_professor(self, first_name, last_name, email, phone, dep, office, - classes, office_time, rcs): - if email is not None: - print(email) - return self.db_conn.execute(""" - INSERT INTO - professor (first_name, last_name, email, phone_number, - department, office_room, classes, office_hours_time, rcs) - VALUES - (%(First_name)s, %(Last_name)s, %(Phone_number)s, %(Email)s, - %(Dep)s, %(Office_room)s, %(Classes)s, %(Office_time)s, %(Rcs_id)s) - ON CONFLICT DO NOTHING - ; - """, { - "First_name": first_name, - "Last_name": last_name, - "Email": email, + def add_professor(self, name, title, email, phone, dep, portfolio, profile_page): + if email is not None: + return self.db_conn.execute(""" + INSERT INTO professor (Email, Name, Title, Phone_number, Department, + Portfolio_page, Profile_page) + VALUES (%(name)s, %(title)s, %(email)s, %(phone_number)s, %(department)s, + %(portfolio_page)s, %(profile_page)s) + ON CONFLICT DO NOTHING; + """, { + "Name": name, + "Title": title, + "Email": email, "Phone_number": phone, - "Dep": dep, - "Office_room": office, - "Classes": classes, - "Office_time": office_time, - "Rcs_id": rcs - } - , False) - else: - return (False, "email cant be none") - - - -def add_bulk_professor(self): - # Load the JSON data from a file - with open('Professors.json') as file: - data = json.load(file) - - # Connect to the SQL database - conn = self.db.get_connection() - - # Loop through each professor record in the JSON data - for record in data: - professor = Professor(email=record['Email'], - first_name=record['Name'], - phone_number=record['Phone'], - department=record['Department'], - office_room=record['Portfolio'], - office_hours_time='', - rcs='') - conn.add(professor) + "Department": dep, + "Portfolio_page": portfolio, + "Profile_page": profile_page, + }) + else: + return False, "Email cannot be None." - # Commit the changes to the database - conn.commit() - self.clear_cache() - return (True,None) + # def add_bulk_professor(self): + # # Load the JSON data from a file + # with open('Professors.json') as file: + # data = json.load(file) - # def add_bulk_professor(self, csv_text): + # # Connect to the SQL database # conn = self.db.get_connection() - # reader = csv.DictReader(csv_text) - # # for each course entry insert sections and course sessions - # with conn.cursor(cursor_factory=RealDictCursor) as transaction: - # for row in reader: - # try: - # #professors - # transaction.execute( - # """ - # INSERT INTO - # profssor( - # name, - # title, - # email, - # phone_number, - # department, - # portfolio_page - # ) - # VALUES ( - # NULLIF(%(Name)s, ''), - # NULLIF(%(Title)s, ''), - # %(Email)s, - # NULLIF(%(Phone_number)s, ''), - # NULLIF(%(Department)s, ''), - # NULLIF(%(Portfolio_page)s, '') - # ) - # ON CONFLICT DO NOTHING; - # """, - # { - # "Name": row['professor_name'], - # "Title": row['professor_title'], - # "Email": row['professor_email'], - # "Phone_number": row['professor_phone_number'], - # "Department": row['professor_department'], - # "Portfolio_page": row['professor_portfolio_page'], - # } - # ) - # except Exception as e: - # print(e) - # conn.rollback() - # return (False, e) + + # # Loop through each professor record in the JSON data + # for record in data: + # professor = Professor(email=record['Email'], + # name=record['Name'], + # phone_number=record['Phone'], + # department=record['Department'], + # portfolio=record['Portfolio'], + # office_hours_time='', + # rcs='') + # conn.add(professor) + + # # Commit the changes to the database # conn.commit() - # # invalidate cache so we can get new classes # self.clear_cache() - # return (True, None) - - + # return (True,None) + + def populate_from_json(self, json_data): + # Connect to the database + conn = self.db_conn.get_connection() + + with conn.cursor(cursor_factory=RealDictCursor) as transaction: + try: + # Iterate over each entry in the JSON data + for entry in json_data: + try: + # Email, + # Name + # Title, + # Phone_number, + # Department, + # Portfolio_page, + # Profile_page + + # Insert professor data into the 'professor' table + transaction.execute( + """ + INSERT INTO professor ( + email, + name, + title, + phone_number, + department, + portfolio_page, + profile_Page + ) + VALUES ( + NULLIF(%(Email)s, ''), -- Use NULL if Email is empty string + NULLIF(%(Name)s, ''), + NULLIF(%(Title)s, ''), + NULLIF(%(Phone)s, ''), + NULLIF(%(Department)s, ''), + NULLIF(%(Portfolio)s, ''), + NULLIF(%(Profile_Page)s, '') + ) + ON CONFLICT DO NOTHING; + """, + { + "Email": entry['Email'], + "Name": entry['Name'], + "Title": entry['Title'], + "Phone": entry['Phone'], + "Department": entry['Department'], + "Portfolio": entry['Portfolio'], + "Profile_Page": entry['Profile Page'] + } + ) + except Exception as e: + # Roll back the transaction and return the exception if an error occurs + print("THIS IS THE EXCEPTION:", e) + conn.rollback() + return (False, e) + except ValueError as ve: + # Return an error message if the JSON data is invalid + return (False, f"Invalid JSON data: {str(ve)}") + + # Commit the transaction if all entries are inserted successfully + conn.commit() + + # Invalidate cache to ensure new data is retrieved + self.clear_cache() + + # Return success status and no error + return (True, None) + + #removes professor if it exists def remove_professor(self, email): if email is not None: sql = """ DELETE FROM professor WHERE - email = '{email}' + email = '%s' """ - error = self.db_conn.execute(sql, None, False) + error = self.db_conn.execute(sql, (email,), False) else: return (False, "email cant be none") return (True, None) @@ -153,62 +161,47 @@ def bulk_delete(self,professors): self.clear_cache() return None - # if you expect the SQL statement to return more than one row of data, you should pass True as the value for multi. + # if you expect the SQL statement to return more than one row of data, + # you should pass True as the value for multi. + def get_professor_info_by_email(self, email): if email is not None: sql = """ - select - * - from - professor - where - email = '%s' - """ % email - info, error = self.db_conn.execute(sql, None, True) - return (info, None) if not error else (False, error) + SELECT + * + FROM + professor + where + email = %s + """ + return self.db_conn.execute(sql, (email,), True) - def get_professor_phone_number_by_email(self, email): - if email is not None: - sql = """ - select - phone_number - from - professor - where - email = '%s' - """ % email - phone_number, error = self.db_conn.execute(sql, None, True) - return (phone_number, None) if not error else (False, error) - - def get_professor_info_by_rcs(self,rcs): - return self.get_professor_info_by_email(rcs+"@rpi.edu") + #seraches professors who are in a certain department + def get_professors_by_department(self,department): + sql = """ + select + * + from + professor + where + department = %s + """ + department, error = self.db_conn.execute(sql, (department,), True) + return (department, None) if not error else (False, error) - def get_professor_rcs_by_email(self,email): + def get_professor_phone_number_by_email(self, email): if email is not None: sql = """ select - rcs + phone_number from professor where - email = '%s' - """ % email - rcs, error = self.db_conn.execute(sql, None, True) - return (rcs, None) if not error else (False, error) + email = %s + """ + info, error = self.db_conn.execute(sql, (email,), True) + return (info, None) if not error else (False, error) - def get_office_hours_by_email(self,email): - if email is not None: - sql = """ - select - office_room - office_hours_time - from - professor - where - email = '%s' - """ % email - office_hours, error = self.db_conn.execute(sql, None, True) - return (office_hours,error) if not error else (False,error) #return as a json def get_all_professors(self): @@ -225,40 +218,25 @@ def get_professor_phone_number_by_email(self, email): from professor where - email = '%s' - """ % email - phone_number, error = self.db_conn.execute(sql, None, True) + email = %s + """ + phone_number, error = self.db_conn.execute(sql, (email,), True) return (phone_number, None) if not error else (False, error) def get_professor_name_by_email(self, email): if email is not None: sql = """ - select - first_name, - last_name - from - professor - where - email = '%s' - """ % email - name, error = self.db_conn.execute(sql, None, True) + SELECT + name + FROM + professor + WHERE + email = %s + """ + name, error = self.db_conn.execute(sql, (email,), True) return (name, None) if not error else (False, error) - - #seraches professors who are in a certain department - def get_professors_by_department(self,department): - sql = """ - select - * - from - professor - where - department = '%s' - """ % department - department, error = self.db_conn.execute(sql, None, True) - return (department, None) if not error else (False, error) - if __name__ == "__main__": csv_text = open('../../../rpi_data/fall-2020.csv', 'r') courses = Professor(connection.db) - courses.populate_from_csv(csv_text) \ No newline at end of file + courses.populate_from_csv(csv_text) diff --git a/src/api/migrations/versions/2020-12-04_init.py b/src/api/migrations/versions/2020-12-04_init.py index b6e44ba50..93a61dc61 100644 --- a/src/api/migrations/versions/2020-12-04_init.py +++ b/src/api/migrations/versions/2020-12-04_init.py @@ -118,13 +118,11 @@ def upgrade(): # op.create_table('professor', # sa.Column('email', sa.VARCHAR(length=255), nullable=False), # sa.Column('first_name', sa.VARCHAR(length=255), nullable=True), - # sa.Column('last_name', sa.VARCHAR(length=255), nullable=True), # sa.Column('phone_number', sa.VARCHAR(length=255), nullable=True), # sa.Column('department', sa.VARCHAR(length=255), nullable=True), - # sa.Column('office_room', sa.VARCHAR(length=255), nullable=True), - # sa.Column('classes', sa.VARCHAR(length=255), nullable=True), - # sa.Column('office_hours_time', sa.VARCHAR(length=255), nullable=True), - # sa.Column('rcs', sa.VARCHAR(length=255), nullable=True), + # sa.Column('Title', sa.VARCHAR(length=255), nullable=True), + # sa.Column('Portfolio', sa.VARCHAR(length=255), nullable=True), + # sa.Column('Portfolio_page', sa.VARCHAR(length=255), nullable=True), # sa.PrimaryKeyConstraint('email') # ) # ### end Alembic commands ### @@ -144,5 +142,5 @@ def downgrade(): op.drop_table('course_corequisite') op.drop_table('course') op.drop_table('admin_settings') - #op.drop_table('professor') + # op.drop_table('professor') # ### end Alembic commands ### diff --git a/src/api/migrations/versions/2023-04-06_professor_table.py b/src/api/migrations/versions/2023-04-06_professor_table.py index 8a4c5e72e..38c42c97b 100644 --- a/src/api/migrations/versions/2023-04-06_professor_table.py +++ b/src/api/migrations/versions/2023-04-06_professor_table.py @@ -16,25 +16,24 @@ depends_on = None +#BUILDS THE TABLE def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #CHANGE COLUMNS op.create_table('professor', sa.Column('email', sa.VARCHAR(length=255), nullable=False), - sa.Column('first_name', sa.VARCHAR(length=255), nullable=True), - sa.Column('last_name', sa.VARCHAR(length=255), nullable=True), + sa.Column('name', sa.VARCHAR(length=255), nullable=True), + sa.Column('title', sa.VARCHAR(length=255), nullable=True), sa.Column('phone_number', sa.VARCHAR(length=255), nullable=True), sa.Column('department', sa.VARCHAR(length=255), nullable=True), - sa.Column('office_room', sa.VARCHAR(length=255), nullable=True), - sa.Column('classes', sa.VARCHAR(length=255), nullable=True), - sa.Column('office_hours_time', sa.VARCHAR(length=255), nullable=True), - sa.Column('rcs', sa.VARCHAR(length=255), nullable=True), + sa.Column('portfolio_page', sa.VARCHAR(length=255), nullable=True), + sa.Column('profile_page', sa.VARCHAR(length=255), nullable=True), sa.PrimaryKeyConstraint('email') ) # ### end Alembic commands ### -# def downgrade(): -# # ### commands auto generated by Alembic - please adjust! ### -# op.drop_table('professor') +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('professor') # ### end Alembic commands ### + diff --git a/src/api/tables/pathways.py b/src/api/tables/pathways.py index 59cbdc8df..2a3974ea0 100644 --- a/src/api/tables/pathways.py +++ b/src/api/tables/pathways.py @@ -6,9 +6,13 @@ class Pathway(Base): __tablename__ = "pathway" - name = Column(VARCHAR(length=255)) + category_name = Column(VARCHAR(length=255)) + pathways_name = Column(VARCHAR(length=255)) description = TEXT - required_courses = Column(TSVECTOR, bool = False) + required_courses = Column(TSVECTOR, bool = False) + #description and list of courses for reuqired_courses #foreign key for courses courses = Column(TSVECTOR, ForeignKey("course.crn")) - compatible_minor = Column(TSVECTOR) \ No newline at end of file + compatible_minor = Column(TSVECTOR) + + # [Arts/Design[Creative Design, Grahpic], ] \ No newline at end of file diff --git a/src/api/tables/professor.py b/src/api/tables/professor.py index d4d128a05..586b222a7 100644 --- a/src/api/tables/professor.py +++ b/src/api/tables/professor.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, ForeignKey +from sqlalchemy import Column from sqlalchemy.dialects.postgresql import VARCHAR from .database import Base @@ -6,22 +6,12 @@ class Professor(Base): __tablename__ = "professor" - email = Column(VARCHAR(length=255), primary_key = True, nullable=False) - name = Column(VARCHAR(length=255), nullable=True) - title = Column(VARCHAR(length=255), nullable=True) - phone_number = Column(VARCHAR(length=255),nullable=True) - department = Column(VARCHAR(length=255), nullable=True) - portfolio_page = Column(VARCHAR(length=255),nullable=True) - office_room = Column(VARCHAR(length=255), nullable=True) - classes = Column(VARCHAR(length=255), ForeignKey("course.crn")) - office_hours_time = Column(VARCHAR(length=255), nullable=True) - rcs = Column(VARCHAR(length=255), nullable = True) - # email = Column(VARCHAR(length=255), primary_key = True, nullable=False) - # first_name = Column(VARCHAR(length=255)) - # last_name = Column(VARCHAR(length=255)) - # phone_number = Column(VARCHAR(length=255)) - # department = Column(VARCHAR(length=255)) - # office_room = Column(VARCHAR(length=255)) - # classes = Column(VARCHAR(length=255), ForeignKey("course.crn")) - # office_hours_time = Column(VARCHAR(length=255)) - # rcs = Column(VARCHAR(length=255)) + Email = Column(VARCHAR(length=255), primary_key=True, nullable=False) + Name = Column(VARCHAR(length=255), nullable = True) + Title = Column(VARCHAR(length=255), nullable=True) + Phone_number = Column(VARCHAR(length=255), nullable=True) + Department = Column(VARCHAR(length=255), nullable=True) + Portfolio_page = Column(VARCHAR(length=255), nullable=True) + Profile_page = Column(VARCHAR(length=255), nullable=True) + + # rcs = Column(VARCHAR(length=255), nullable = True) diff --git a/src/web/src/components/Header.vue b/src/web/src/components/Header.vue index 72ef79e28..deb565383 100644 --- a/src/web/src/components/Header.vue +++ b/src/web/src/components/Header.vue @@ -50,14 +50,14 @@ Pathways - - - Finals - Professors + + + Finals + diff --git a/src/web/src/pages/Admin.vue b/src/web/src/pages/Admin.vue index 7a1acc847..70bee1771 100644 --- a/src/web/src/pages/Admin.vue +++ b/src/web/src/pages/Admin.vue @@ -28,6 +28,10 @@ > Edit Professors + + Import Professors via JSON + + @@ -41,6 +45,10 @@ + + + + @@ -56,6 +64,7 @@ import UploadCsv from "@/pages/UploadCsv"; import EditSemesters from "@/pages/EditSemesters"; import SetDefault from "@/pages/SetDefault"; import EditProfessors from "@/pages/EditProfessors"; +import UploadJson from "@/pages/UploadJson.vue"; export default { name: "AdminPage", @@ -64,10 +73,11 @@ export default { EditSemesters, SetDefault, EditProfessors, + UploadJson, // ManageAccounts, }, data() { return {}; }, }; - + \ No newline at end of file diff --git a/src/web/src/pages/EditProfessors.vue b/src/web/src/pages/EditProfessors.vue index 051813612..f443dc82f 100644 --- a/src/web/src/pages/EditProfessors.vue +++ b/src/web/src/pages/EditProfessors.vue @@ -33,7 +33,7 @@ /> - Add message: + Testing Result: {{ this.result }} - Get Prof + Professors - Get Prof Name + Professor Name - Get Prof Department - - - Get Prof Office Hours + Department - Get Prof Number By Email - - - Get Prof By Rcs - - - Get Prof By Email + Phone Number Add Prof Add Prof Test - Bulk Add + Remove Prof Bulk Delete @@ -81,9 +72,7 @@ import { getProfessors, get_professor_name_by_email, get_professor_from_department, - get_office_hours, get_professor_phone_number_by_email, - get_professor_info_by_rcs, get_professor_info_by_email, } from "@/services/YacsService"; import { @@ -120,21 +109,11 @@ export default { this.result = get_professor_from_department(this.department); console.log(this.result); }, - getOfficeHours() { - console.log("get_office_hours"); - this.result = get_office_hours(this.email); - console.log(this.result); - }, getProfNumberByEmail() { console.log("get_professor_phone_number_by_email"); this.result = get_professor_phone_number_by_email(this.email); console.log(this.result); }, - get_professor_info_by_rcs() { - console.log("get_professor_info_by_rcs"); - this.result = get_professor_info_by_rcs(this.rcs); - console.log(this.result); - }, getProfByEmail() { console.log("get_professor_info_by_email"); this.result = get_professor_info_by_email(this.email); @@ -155,9 +134,9 @@ export default { this.result = addProfessorsTest(); console.log(this.result); }, - BulkAdd() { - console.log("BulkAdd"); - }, + // // BulkAdd() { + // // console.log("BulkAdd"); + // }, BulkDelete() { console.log("BulkDelete"); }, @@ -210,4 +189,4 @@ $primary: #007bff; background-color: $primary; } } - + \ No newline at end of file diff --git a/src/web/src/pages/ProfExplorer.vue b/src/web/src/pages/ProfExplorer.vue index 21534b06d..17fd6f0b2 100644 --- a/src/web/src/pages/ProfExplorer.vue +++ b/src/web/src/pages/ProfExplorer.vue @@ -157,7 +157,7 @@ :fontSize="1.3" loadingMessage="Professors" :topSpacing="30" - /> + /> @@ -194,13 +194,13 @@ export default { var count = 0; var departments = []; var dept = ""; - for (let i = 0; i < this.professors.length; i++) { + for (let i = 0; i < this.professors.length; i++){ dept = this.professors[i]["Department"]; - if (dept == "") { + if (dept == ""){ dept = this.professors[i]["Portfolio"]; } - if (!departments.includes(dept)) { - departments.push(dept); + if (!departments.includes(dept)){ + departments.push(dept) } } departments.sort(); @@ -208,14 +208,14 @@ export default { let ret = []; let col1 = []; let col2 = []; - for (var i = 0; i < departments.length; i++) { + for (var i = 0; i < departments.length; i++){ var tmp = { - Department: departments[i], - Professors: [], + "Department": departments[i], + "Professors": [], }; - for (var j = 0; j < this.professors.length; j++) { + for (var j = 0; j < this.professors.length; j++){ dept = this.professors[j]["Department"]; - if (dept == "") { + if (dept == ""){ dept = this.professors[i]["Portfolio"]; } var name = this.professors[j]["Name"]; diff --git a/src/web/src/pages/ProfPage.vue b/src/web/src/pages/ProfPage.vue index c970e94c9..66f752eca 100644 --- a/src/web/src/pages/ProfPage.vue +++ b/src/web/src/pages/ProfPage.vue @@ -11,7 +11,7 @@ - Department: {{ prof.Department }} + Department: {{prof.Department}} diff --git a/src/web/src/pages/UploadJson.vue b/src/web/src/pages/UploadJson.vue new file mode 100644 index 000000000..cc19e5215 --- /dev/null +++ b/src/web/src/pages/UploadJson.vue @@ -0,0 +1,104 @@ + + + + Import Data + + Input professor data as JSON + + + + + Upload JSON file + + + + + + + + Make Public + + + + + + + + + + + + \ No newline at end of file diff --git a/src/web/src/plugins/fontawesome-vue.js b/src/web/src/plugins/fontawesome-vue.js index b02033aee..e8e2bbbcd 100644 --- a/src/web/src/plugins/fontawesome-vue.js +++ b/src/web/src/plugins/fontawesome-vue.js @@ -15,6 +15,7 @@ import { faFileAlt, } from "@fortawesome/free-solid-svg-icons"; + library.add( faPaperPlane, faMoon, diff --git a/src/web/src/services/AdminService.js b/src/web/src/services/AdminService.js index e0c602ae7..f3e6a3ba5 100644 --- a/src/web/src/services/AdminService.js +++ b/src/web/src/services/AdminService.js @@ -7,6 +7,9 @@ const client = axios.create({ export const uploadCsv = (formData) => client.post("/bulkCourseUpload", formData); +export const uploadJSON = (formData) => + client.post("/bulkProfessorUpload", formData); + export const mapDateRangeToSemesterPart = (formData) => client.post("/mapDateRangeToSemesterPart", formData); diff --git a/src/web/src/services/YacsService.js b/src/web/src/services/YacsService.js index ff7df1b12..779dcddc2 100644 --- a/src/web/src/services/YacsService.js +++ b/src/web/src/services/YacsService.js @@ -158,14 +158,8 @@ export const get_professor_name_by_email = (email) => export const get_professor_from_department = (department) => client.get("/professor/department/" + department).then((res) => res.data); -export const get_office_hours = (email) => - client.get("/professor/office_hours/" + email).then((res) => res.data); - export const get_professor_phone_number_by_email = (email) => client.get("/professor/phone_number/" + email).then((res) => res.data); -export const get_professor_info_by_rcs = (rcs) => - client.get("/professor/rcs/" + rcs).then((res) => res.data); - export const get_professor_info_by_email = (email) => client.get("/professor/email/" + email).then((res) => res.data);
{{ this.result }}