Added a lot of support for new visual framework. Still WIP

This commit is contained in:
Andrew Lalis 2019-05-16 19:30:00 +02:00 committed by andrewlalis
parent 1aa6895aec
commit 13dd59aa8f
21 changed files with 505 additions and 346 deletions

View File

@ -37,7 +37,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.and() .and()
.authorizeRequests() .authorizeRequests()
.antMatchers("/css/**", "/images/**") .antMatchers("/css/**", "/images/**", "/javascript/**")
.permitAll() .permitAll()
.and() .and()

View File

@ -0,0 +1,48 @@
package nl.andrewlalis.teaching_assistant_assistant.controllers;
import nl.andrewlalis.teaching_assistant_assistant.model.dto.NewUserRegistrationDTO;
import nl.andrewlalis.teaching_assistant_assistant.model.repositories.CourseRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.Arrays;
/**
* Controller for the registration page which is used for the creation of new accounts.
*/
@Controller
public class RegisterController {
private final Logger logger = LogManager.getLogger(RegisterController.class);
private CourseRepository courseRepository;
private static final String[] personTypes = {
"Student",
"Teaching Assistant",
"Professor",
"Administrator"
};
protected RegisterController(CourseRepository courseRepository) {
this.courseRepository = courseRepository;
}
@GetMapping("/register")
public String get(Model model) {
model.addAttribute("newUserRegistration", new NewUserRegistrationDTO(Arrays.asList(personTypes), this.courseRepository.findAll()));
return "register";
}
@PostMapping("/register")
public String post(@ModelAttribute NewUserRegistrationDTO newUserRegistration) {
logger.info("Received new registration: " + newUserRegistration);
return "redirect:/login";
}
}

View File

@ -18,7 +18,7 @@ public class CreateCourse extends UserPageController {
@GetMapping("/courses/create") @GetMapping("/courses/create")
public String get(Model model) { public String get(Model model) {
Course course = new Course("no name", "no code"); Course course = new Course(null, null);
model.addAttribute("course", course); model.addAttribute("course", course);
return "courses/create"; return "courses/create";
} }

View File

@ -36,7 +36,7 @@ public class StudentCreateController extends UserPageController {
@GetMapping("/students/create") @GetMapping("/students/create")
public String getCreate(Model model) { public String getCreate(Model model) {
model.addAttribute("student", new Student("First Name", "Last Name", "Email Address", "Github Username", 1234567)); model.addAttribute("student", new Student(null, null, null, null, 1234567));
model.addAttribute("courses", this.courseRepository.findAll()); model.addAttribute("courses", this.courseRepository.findAll());
return "students/create"; return "students/create";

View File

@ -0,0 +1,95 @@
package nl.andrewlalis.teaching_assistant_assistant.model.dto;
import nl.andrewlalis.teaching_assistant_assistant.model.Course;
import java.util.List;
/**
* A data transfer object to aid in the registration of a new authenticated user. This object therefore contains all the
* data that potential users enter prior to the actual creation of a new user.
*/
public class NewUserRegistrationDTO {
private String firstName;
private String lastName;
private String emailAddress;
private String username;
private String password;
private String passwordConfirm;
private String selectedPersonType;
private List<String> availablePersonTypes;
private Iterable<Course> availableCourses;
public NewUserRegistrationDTO(List<String> availablePersonTypes, Iterable<Course> availableCourses) {
this.availablePersonTypes = availablePersonTypes;
this.availableCourses = availableCourses;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public List<String> getAvailablePersonTypes() {
return availablePersonTypes;
}
public Iterable<Course> getAvailableCourses() {
return availableCourses;
}
public String getSelectedPersonType() {
return this.selectedPersonType;
}
}

View File

@ -0,0 +1,18 @@
package nl.andrewlalis.teaching_assistant_assistant.model.repositories;
import nl.andrewlalis.teaching_assistant_assistant.model.security.Role;
import org.springframework.data.repository.CrudRepository;
import java.util.Optional;
/**
* The repository for all roles to which users may be assigned.
*/
public interface RoleRepository extends CrudRepository<Role, Long> {
/**
* Try to find a role by the given name.
* @return An optional Role that has the given name.
*/
public Optional<Role> findByName(String name);
}

View File

@ -1,59 +1,7 @@
/* Set the font for the whole website here. */ /*.btn-primary {*/
body { /* background-color: green;*/
font-family: sans-serif; /*}*/
background-color: white;
padding-bottom: 70px;
}
.content_container { /*.btn-primary:hover {*/
width: 50%; /* background-color: darkgreen;*/
margin-left: auto; /*}*/
margin-right: auto;
text-align: left;
font-size: 16px;
color: black;
}
.sidebar_container {
width: 20%;
height: 100%;
position: fixed;
top: 70px;
right: 0;
}
.sidebar_block {
margin: 20px 0 20px 0;
padding: 20px;
background-color: green;
color: whitesmoke;
}
.sidebar_block a {
text-decoration: underline;
color: inherit;
}
.white_link {
text-decoration: underline;
color: white;
}
.sidebar_block a:hover {
color: lightgreen;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
.page_row {
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
}
label {
font-weight: bold;
}

File diff suppressed because one or more lines are too long

View File

@ -1,39 +1,27 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Courses', content=~{::#content}, actions=~{::#actions})}" lang="en">
<head>
<title>Courses</title>
</head>
<body> <body>
<div id="content"> <div id="actions">
<h1>Courses</h1> <a class="btn btn-primary m-1" th:href="@{/courses/create}">Create New Course</a>
<hr>
<ul>
<li th:each="course: ${courses}">
<h2><a th:href="@{/courses/{code}(code=${course.getCode()})}" th:text="${course.getName()}"></a></h2>
<ul>
<li>Code: <span th:text="${course.getCode()}"></span></li>
<li>Created on: <span th:text="${course.getCreatedOn()}"></span></li>
<li>Students: <span th:text="${course.getStudents().size()}"></span></li>
<li>Teaching Assistants: <span th:text="${course.getTeachingAssistants().size()}"></span></li>
<li>Student Teams: <span th:text="${course.getStudentTeams().size()}"></span></li>
<li>Teaching Assistant Teams: <span th:text="${course.getTeachingAssistantTeams().size()}"></span></li>
<li>Number of Active Students (in a team): <span th:text="${course.getNumberOfStudentsInTeams()}"></span></li>
</ul>
</li>
</ul>
</div> </div>
<div id="sidebar"> <div id="content" class="container-fluid">
<div class="sidebar_block"> <div class="col-sm-12 col-md-6 offset-3">
<a href="/courses/create">Create new course</a> <div class="list-group">
</div> <a th:each="course: ${courses}" class="list-group-item list-group-item-action flex-column align-items-start" th:href="@{/courses/{code}(code=${course.getCode()})}">
<div class="sidebar_block"> <div class="d-flex w-100 justify-content-between">
Do something else <h4 class="mb-1" th:text="${course.getName()}"></h4>
</div> <small th:text="${course.getCode()}"></small>
<div class="sidebar_block"> </div>
Click this link! <ul>
<li><span class="badge badge-primary" th:text="${course.getStudentTeams().size()}"></span> Student Teams</li>
<li><span class="badge badge-primary" th:text="${course.getNumberOfStudentsInTeams()}"></span> Active Students</li>
<li><span class="badge badge-primary" th:text="${course.getTeachingAssistants().size()}"></span> Teaching Assistants</li>
</ul>
<small>Created on <span th:text="${course.getCreatedOn()}"></span></small>
</a>
</div>
</div> </div>
</div> </div>

View File

@ -1,43 +1,35 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Create New Course', content=~{::#content})}" lang="en">
<head>
<title>Create a Course</title>
</head>
<body> <body>
<div id="content"> <div id="content" class="row justify-content-center">
<h1>Create New Course</h1> <form th:action="@{/courses}" th:object="${course}" method="post">
<div class="form-group">
<form action="#" th:action="@{/courses}" th:object="${course}" method="post"> <label for="course_name_input">Name</label>
<div class="page_row"> <input id="course_name_input" type="text" class="form-control" th:field="*{name}" required/>
<label for="course_name_input">Name:</label>
<input id="course_name_input" type="text" th:field="*{name}" required/>
</div> </div>
<div class="page_row"> <div class="form-group">
<label for="course_code_input">Code:</label> <label for="course_code_input">Code</label>
<input id="course_code_input" type="text" th:field="*{code}" required/> <input id="course_code_input" type="text" class="form-control" th:field="*{code}" required/>
<small class="form-text text-muted">Unique identifying code for this course.</small>
</div> </div>
<div class="page_row"> <div class="form-group">
<label for="course_github_organization_name_input">Github Organization:</label> <label for="course_github_organization_name_input">Github Organization</label>
<input id="course_github_organization_name_input" type="text" th:field="*{githubOrganizationName}" required/> <input id="course_github_organization_name_input" type="text" class="form-control" th:field="*{githubOrganizationName}" required/>
</div> </div>
<div class="page_row"> <div class="form-group">
<label for="course_github_api_key_input">Github API Key:</label> <label for="course_github_api_key_input">Github API Key</label>
<input id="course_github_api_key_input" type="text" th:field="*{apiKey}" required/> <input id="course_github_api_key_input" type="text" class="form-control" th:field="*{apiKey}" required/>
<small class="form-text text-muted">Needed to manage student repositories.</small>
</div> </div>
<div class="page_row"> <input class="btn btn-primary" type="submit" value="Create"/>
<button type="submit">Submit</button>
</div>
</form> </form>
</div> </div>
<div id="sidebar">
</div>
</body> </body>
</html> </html>

View File

@ -1,40 +1,35 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title=${course.getName()}, content=~{::#content}, actions=~{::#actions})}">
<head>
<meta charset="UTF-8">
<title th:text="${course.getName()}"></title>
</head>
<body> <body>
<div id="content"> <div id="actions">
<h1><span th:text="${course.getName()}"></span> (Code: <span th:text="${course.getCode()}"></span>)</h1> <a class="btn btn-primary m-1" th:href="@{/courses/{code}/import_students(code=${course.getCode()})}">Import Students From CSV</a>
<hr> <a class="btn btn-primary m-1" th:href="@{/courses/{code}/import_teaching_assistants(code=${course.getCode()})}">Import Teaching Assistants From CSV</a>
<ul>
<li>
Github Organization: <a th:href="@{${'https://www.github.com/' + course.getGithubOrganizationName()}}" th:text="${course.getGithubOrganizationName()}"></a>
</li>
<li>
<a th:href="@{/courses/{code}/teaching_assistant_teams(code=${course.getCode()})}">Teaching Assistant Teams</a>
</li>
<li>
<a th:href="@{/courses/{code}/student_teams(code=${course.getCode()})}">Student Teams</a>
</li>
<li>
<a th:href="@{/courses/{code}/students(code=${course.getCode()})}">All Students</a>
</li>
<li>
<a th:href="@{/courses/{code}/teaching_assistants(code=${course.getCode()})}">All Teaching Assistants</a>
</li>
</ul>
</div> </div>
<div id="sidebar"> <div id="content" class="row justify-content-center">
<div class="sidebar_block"> <div class="col-sm-12 col-md-6">
<a th:href="@{/courses/{code}/import_students(code=${course.getCode()})}">Import students from CSV</a> <div class="list-group">
</div> <a class="list-group-item list-group-item-action" th:href="@{${'https://www.github.com/' + course.getGithubOrganizationName()}}">
<div class="sidebar_block"> Github Organization: <span th:text="${course.getGithubOrganizationName()}"></span>
<a th:disabled="true" th:href="@{/courses/{code}/import_teaching_assistants(code=${course.getCode()})}">Import teaching assistants from CSV</a> </a>
<a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center" th:href="@{/courses/{code}/teaching_assistant_teams(code=${course.getCode()})}">
Teaching Assistant Teams
<span class="badge badge-primary" th:text="${course.getTeachingAssistantTeams().size()}"></span>
</a>
<a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center" th:href="@{/courses/{code}/student_teams(code=${course.getCode()})}">
Student Teams
<span class="badge badge-primary" th:text="${course.getStudentTeams().size()}"></span>
</a>
<a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center" th:href="@{/courses/{code}/students(code=${course.getCode()})}">
Students
<span class="badge badge-primary" th:text="${course.getStudents().size()}"></span>
</a>
<a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center" th:href="@{/courses/{code}/teaching_assistants(code=${course.getCode()})}">
Teaching Assistants
<span class="badge badge-primary" th:text="${course.getTeachingAssistants().size()}"></span>
</a>
</div>
</div> </div>
</div> </div>

View File

@ -1,34 +1,77 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}" lang="en"> <html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Home', content=~{::#content})}" lang="en">
<head>
<title>Homepage</title>
</head>
<body> <body>
<div id="content"> <div id="content" class="container-fluid">
<h1>Teaching Assistant Assistant</h1> <div class="row justify-content-center">
<hr> <div class="col-6">
<h3>Welcome to the Teaching Assistant Assistant, <span th:text="${user.getPerson().getFullName()}"></span>.</h3>
<p> <p>
Welcome to the Teaching Assistant Assistant, <span th:text="${user.getPerson().getFullName()}"></span>. To find the courses in this application please follow the link to <a th:href="@{/courses}">courses</a>. To find the courses in this application please follow the link to <a th:href="@{/courses}">courses</a>.
</p> </p>
<p> <p>
This application makes it easy to sift through lots of student groups that are usually handled manually in some This application makes it easy to sift through lots of student groups that are usually handled manually in some
spreadsheet. By integrating all data into one web application it is possible to access the information you need spreadsheet. By integrating all data into one web application it is possible to access the information you need
faster, and make coordinated changes without fear of introducing inconsistencies or errors. faster, and make coordinated changes without fear of introducing inconsistencies or errors.
</p> </p>
</div> </div>
<div id="sidebar">
<div class="sidebar_block">
This is an example sidebar block.
</div> </div>
<div id="generate_courses_block" class="sidebar_block">
<a href="/courses/generate">Click here to generate test data.</a> <div class="row justify-content-center">
</div> <div class="col-4">
<div class="sidebar_block"> <h5>Lights, Camera, Action!</h5>
Another sidebar block with a lot more text in it, so that the text should properly wrap to the next lines if needed.
<p>
Throughout the application, you'll find many of these action buttons, which you can use to interact with various objects or pages. Each action will have some accompanying text that describes the results of the action, and anything else you might need to be aware of.
</p>
<p>
Sometimes you'll need special permission to perform an action, so if you don't have permission to do so, the action button will appear grayed out, like one of the actions on the right is.
</p>
</div>
<div class="col-6">
<div class="card-columns">
<div class="card" style="width: 18rem;">
<div class="card-body">
<a class="btn btn-primary" href="#">
Do Action
</a>
<p class="card-text">
This text will tell you a little bit about what this action does, so that you think twice before you do some irreparable harm.
</p>
</div>
</div>
<div class="card" style="width: 18rem;">
<div class="card-body">
<a class="btn btn-primary" href="#">
Another Action
</a>
<p class="card-text">
Once again, please read these instructions before pressing that button, no matter how appealing it looks.
</p>
</div>
</div>
<div class="card" style="width: 18rem;">
<div class="card-body">
<a class="btn btn-primary disabled" href="#">
Do Action
</a>
<p class="card-text">
As you can see, the action button above is <em>disabled</em>, meaning that one of two things happened:
</p>
<ol>
<li>You don't have permission to perform the action.</li>
<li>This action is still a work-in-progress.</li>
</ol>
<p>
If you believe this to be an error, please contact the site administrator and make sure to mention your username and which action you need to perform.
</p>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>

View File

@ -1,34 +1,45 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" th:fragment="layout (title, content, sidebar_content)" xmlns:th="http://www.thymeleaf.org"> <html lang="en" th:fragment="layout (title, content)" xmlns:th="http://www.thymeleaf.org">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title th:replace="${title}">basic_page</title> <title th:text="${title}">basic_page</title>
<link rel="stylesheet" href="../../../resources/static/css/style.css" th:href="@{/css/style.css}" />
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/>
<link rel="icon" th:href="@{/images/favicon.ico}"/> <link rel="icon" th:href="@{/images/favicon.ico}"/>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/>
<script th:src="@{/javascript/bootstrap.bundle.min.js}"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<link rel="stylesheet" href="../../../resources/static/css/style.css" th:href="@{/css/style.css}" />
</head> </head>
<body> <body>
<!-- Only show the header if the user is authenticated. -->
<header th:if="${user != null}"> <header th:if="${user != null}">
<div th:replace="~{fragments/header :: header}"></div> <div th:replace="~{fragments/header :: header}"></div>
</header> </header>
<div class="content_container"> <div class="content_container container-fluid">
<div th:replace="${content}"> <div class="row">
<div class="col">
<h1 class="text-center" th:text="${title}"></h1>
<hr>
</div>
</div>
<!-- If the page controller specifies some actions, add them here as cards. -->
<th:block th:if="${actions != null}">
<div th:include="${actions}" class="row justify-content-center mb-2">
</div>
</th:block>
<div th:replace="${content}" class="row">
<p> <p>
Basic page content block. Basic page content block.
</p> </p>
</div> </div>
</div> </div>
<div class="sidebar_container">
<div th:replace="${sidebar_content}">
<p>
Basic page sidebar block.
</p>
</div>
</div>
<div th:replace="~{fragments/footer :: footer}"></div> <div th:replace="~{fragments/footer :: footer}"></div>
</body> </body>

View File

@ -1,33 +0,0 @@
<!DOCTYPE html>
<html lang="en" th:fragment="layout (title, content, sidebar_content)" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:replace="${title}">basic_page</title>
<link rel="stylesheet" href="../../../resources/static/css/style.css" th:href="@{/css/style.css}" />
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/>
<link rel="icon" th:href="@{/images/favicon.ico}"/>
</head>
<body>
<header th:replace="~{fragments/header :: header}"></header>
<div class="content_container">
<div th:replace="${content}">
<p>
Basic page content block.
</p>
</div>
</div>
<div class="sidebar_container">
<div th:replace="${sidebar_content}">
<p>
Basic page sidebar block.
</p>
</div>
</div>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>

View File

@ -1,16 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}" lang="en"> <html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Login', content=~{::#content})}" lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" type="text/css"/>
</head>
<body> <body>
<section id="content" class="container"> <section id="content" class="container">
<div class="row justify-content-center">
<h1>Teaching Assistant <em>Assistant</em></h1>
</div>
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="alert alert-danger" th:if="${param.error}"> <div class="alert alert-danger" th:if="${param.error}">
@ -40,16 +33,12 @@
<input id="password_input" class="form-control" type="password" name="password"/> <input id="password_input" class="form-control" type="password" name="password"/>
</div> </div>
<input type="submit" value="Login"/> <input class="btn btn-primary" type="submit" value="Login"/>
<a class="white_link" th:href="@{/register}">Don't have an account? Sign up here!</a> <a class="btn btn-secondary btn-sm" th:href="@{/register}">Don't have an account? Sign up here!</a>
</form> </form>
</div> </div>
</section> </section>
<div id="sidebar">
</div>
</body> </body>
</html> </html>

View File

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Register', content=~{::#content})}" lang="en">
<body>
<section id="content" class="container">
<div class="row">
<div class="col">
<p>
Here you can register to create a new account to access the information provided by this application, whether you are a professor, teaching assistant, or student. After filling out this submission form, you'll receive an email with a link to verify that you are who you say you are, after which your account will be activated.
</p>
</div>
</div>
<div class="row justify-content-center">
<form th:action="@{/register}" method="post" th:object="${newUserRegistration}">
<div class="form-row">
<div class="col">
<label for="first_name_input">First Name</label>
<input id="first_name_input" class="form-control" type="text" th:field="*{firstName}" required/>
</div>
<div class="col">
<label for="last_name_input">Last Name</label>
<input id="last_name_input" class="form-control" type="text" th:field="*{lastName}" required/>
</div>
</div>
<div class="form-row">
<div class="col">
<label for="email_input">Email</label>
<input id="email_input" class="form-control" type="text" th:field="*{emailAddress}" required/>
</div>
</div>
<div class="form-row">
<div class="col">
<label for="username_input">Username</label>
<input id="username_input" class="form-control" type="text" th:field="*{username}" required/>
</div>
</div>
<div class="form-row">
<div class="col">
<label for="role_select">I am a</label>
<select id="role_select" class="form-control" th:field="*{selectedPersonType}">
<option th:each="personType: ${newUserRegistration.getAvailablePersonTypes()}" th:text="${personType}" th:value="${personType}"></option>
</select>
</div>
</div>
<div class="form-row">
<div class="col">
<label for="password_input">Password</label>
<input id="password_input" class="form-control" type="password" th:field="*{password}" required/>
</div>
<div class="col">
<label for="password_confirm_input">Confirm Password</label>
<input id="password_confirm_input" class="form-control" type="password" th:field="*{passwordConfirm}" required/>
</div>
</div>
<div class="form-row mt-1">
<div class="col">
<input class="btn btn-primary" type="submit" value="Submit"/>
</div>
</div>
</form>
</div>
</section>
</body>
</html>

View File

@ -1,15 +1,17 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Students', content=~{::#content}, actions=~{::#actions})}">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Students</title> <title>Students</title>
</head> </head>
<body> <body>
<div id="content"> <div id="actions">
<h1>All Students</h1> <a class="btn btn-primary m-1" th:href="@{/students/create}">Create Student</a>
</div>
<table> <div id="content" class="row">
<table class="table">
<tr> <tr>
<th>Student</th> <th>Student</th>
<th>Student Number</th> <th>Student Number</th>
@ -44,11 +46,5 @@
</table> </table>
</div> </div>
<div id="sidebar">
<div class="sidebar_block">
<a th:href="@{/students/create}">Create Student</a>
</div>
</div>
</body> </body>
</html> </html>

View File

@ -1,59 +1,66 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Create New Student', content=~{::#content})}">
<head>
<title>Create a Student</title>
</head>
<body> <body>
<div id="content"> <div id="content" class="row justify-content-center">
<h1>Create New Student</h1> <div class="col-sm-12 col-md-6">
<form th:action="@{/students/create}" th:object="${student}" method="post" enctype="application/x-www-form-urlencoded">
<div class="form-row">
<div class="col">
<label for="student_first_name_input">First Name</label>
<input id="student_first_name_input" class="form-control" type="text" th:field="*{firstName}" placeholder="Elon" required />
</div>
<div class="col">
<label for="student_last_name_input">Last Name</label>
<input id="student_last_name_input" class="form-control" type="text" th:field="*{lastName}" placeholder="Musk" required />
</div>
</div>
<form action="#" th:action="@{/students/create}" th:object="${student}" method="post" enctype="application/x-www-form-urlencoded"> <div class="form-row">
<div class="page_row"> <div class="col">
<label for="student_first_name_input">First Name:</label> <label for="student_email_input">Email Address</label>
<input id="student_first_name_input" type="text" th:field="*{firstName}" required /> <input id="student_email_input" class="form-control" type="email" th:field="*{emailAddress}" placeholder="me@example.com" required />
</div> </div>
</div>
<div class="page_row"> <div class="form-row">
<label for="student_last_name_input">Last Name:</label> <div class="col">
<input id="student_last_name_input" type="text" th:field="*{lastName}" required /> <label for="student_github_username_input">Github Username</label>
</div> <input id="student_github_username_input" class="form-control" type="text" th:field="*{githubUsername}" placeholder="username" required />
</div>
</div>
<div class="page_row"> <div class="form-row">
<label for="student_email_input">Email Address:</label> <div class="col">
<input id="student_email_input" type="email" th:field="*{emailAddress}" required /> <label for="student_number_input">Student Number</label>
</div> <input id="student_number_input" class="form-control" type="number" th:field="*{studentNumber}" value="" placeholder="1234567" required />
</div>
</div>
<div class="page_row"> <div class="form-row">
<label for="student_github_username_input">Github Username:</label> <div class="col">
<input id="student_github_username_input" type="text" th:field="*{githubUsername}" required /> <label for="student_course_select">Add this student to a course?</label>
</div> <select id="student_course_select" class="form-control" name="course_code">
<option value="NO_COURSE_SELECTED">None</option>
<option
th:each="course: ${courses}"
th:value="${course.getCode()}"
th:text="${course.getName()}"
></option>
</select>
<small class="form-text text-muted">This can also be done later at this student's page.</small>
</div>
</div>
<div class="page_row"> <div class="form-row mt-1">
<label for="student_number_input">Student Number:</label> <div class="col">
<input id="student_number_input" type="number" th:field="*{studentNumber}" required /> <input class="btn btn-primary" type="submit" value="Submit" />
</div> </div>
</div>
<div class="page_row"> </form>
<label for="student_course_select">Select a course to add the student to:</label> </div>
<select id="student_course_select" name="course_code">
<option value="NO_COURSE_SELECTED">None</option>
<option
th:each="course: ${courses}"
th:value="${course.getCode()}"
th:text="${course.getName()}"
></option>
</select>
</div>
<div class="page_row">
<button type="submit">Submit</button>
</div>
</form>
</div>
<div id="sidebar">
</div> </div>
</body> </body>

View File

@ -1,13 +1,13 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title=${student.getFullName()}, content=~{::#content}, actions=~{::#actions})}">
<head>
<title>Student</title>
</head>
<body> <body>
<div id="content"> <div id="actions">
<h1>Student: <span th:text="${student.getFullName()}"></span></h1> <a class="btn btn-primary m-1" th:href="@{/students/{id}/edit(id=${student.getId()})}">Edit</a>
</div>
<div id="content" class="row">
<ul> <ul>
<li> <li>
Student Number: <code th:text="${student.getStudentNumber()}"></code> Student Number: <code th:text="${student.getStudentNumber()}"></code>
@ -29,11 +29,5 @@
</ul> </ul>
</div> </div>
<div id="sidebar">
<div class="sidebar_block">
<a th:href="@{/students/{id}/edit(id=${student.getId()})}">Edit</a>
</div>
</div>
</body> </body>
</html> </html>

View File

@ -1,22 +1,28 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title='Teaching Assistants', content=~{::#content})}">
<head>
<meta charset="UTF-8">
<title>Teaching Assistants</title>
</head>
<body> <body>
<div id="content"> <div id="content">
<h1>All Teaching Assistants</h1> <table class="table">
<tr>
<table> <th>Teaching Assistant</th>
<th>Github Username</th>
<th>Email</th>
<th>Courses</th>
<th>Delete</th>
</tr>
<tr th:each="teachingAssistant: ${teaching_assistants}"> <tr th:each="teachingAssistant: ${teaching_assistants}">
<td> <td>
<a th:href="@{/teaching_assistants/{id}(id=${teachingAssistant.getId()})}"><span th:text="${teachingAssistant.getFullName()}"></span></a> <a th:href="@{/teaching_assistants/{id}(id=${teachingAssistant.getId()})}"><span th:text="${teachingAssistant.getFullName()}"></span></a>
</td> </td>
<td th:text="${teachingAssistant.getGithubUsername()}"></td> <td th:text="${teachingAssistant.getGithubUsername()}"></td>
<td th:text="${teachingAssistant.getEmailAddress()}"></td> <td th:text="${teachingAssistant.getEmailAddress()}"></td>
<td th:text="${teachingAssistant.getId()}"></td> <td>
<div th:each="course: ${teachingAssistant.getCourses()}">
<a th:href="@{/courses/{code}(code=${course.getCode()})}" th:text="${course.getName()}"></a><br>
</div>
</td>
<td> <td>
<a th:href="@{/teaching_assistants/{id}/delete(id=${teachingAssistant.getId()})}">Delete</a> <a th:href="@{/teaching_assistants/{id}/delete(id=${teachingAssistant.getId()})}">Delete</a>
</td> </td>
@ -24,9 +30,5 @@
</table> </table>
</div> </div>
<div id="sidebar">
</div>
</body> </body>
</html> </html>

View File

@ -1,33 +1,21 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (~{::title}, ~{::#content}, ~{::#sidebar})}"> <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="~{layouts/basic_page :: layout (title=${teachingAssistant.getFullName()}, content=~{::#content})}">
<head>
<title>Teaching Assistant</title>
</head>
<body> <body>
<div id="content"> <div id="content" class="row justify-content-center">
<h1>Teaching Assistant: <span th:text="${teachingAssistant.getFullName()}"></span></h1> <div class="col-sm-12 col-md-6">
<div class="list-group">
<ul> <a class="list-group-item list-group-item-action" th:text="'Email: ' + ${teachingAssistant.getEmailAddress()}" th:href="'mailto: ' + ${teachingAssistant.getEmailAddress()}"></a>
<li> <a class="list-group-item list-group-item-action" th:text="'Github Username: ' + ${teachingAssistant.getGithubUsername()}" th:href="'https://www.github.com/' + ${teachingAssistant.getGithubUsername()}" target="_blank"></a>
Email: <code th:text="${teachingAssistant.getEmailAddress()}"></code> <div class="list-group-item">
</li> <h5>Courses</h5>
<li> <div th:each="course: ${teachingAssistant.getCourses()}">
Github Username: <code th:text="${teachingAssistant.getGithubUsername()}"></code> <a class="list-group-item-action" th:text="${course.getName()}" th:href="@{/courses/{code}(code=${course.getCode()})}"></a><br>
</li> </div>
<li> </div>
Courses: </div>
<ul> </div>
<li th:each="course: ${teachingAssistant.getCourses()}">
<a th:href="@{/courses/{code}(code=${course.getCode()})}"><span th:text="${course.getName()}"></span></a>
</li>
</ul>
</li>
</ul>
</div>
<div id="sidebar">
</div> </div>
</body> </body>