Improvements and new version in development #5
Binary file not shown.
Binary file not shown.
|
@ -1,14 +1,12 @@
|
||||||
package nl.andrewlalis;
|
package nl.andrewlalis;
|
||||||
|
|
||||||
import nl.andrewlalis.model.Student;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.model.database.DbUtil;
|
import nl.andrewlalis.command.executables.*;
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
import nl.andrewlalis.ui.control.command.executables.*;
|
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
import nl.andrewlalis.ui.view.StartView;
|
||||||
import nl.andrewlalis.util.CommandLine;
|
import nl.andrewlalis.util.CommandLine;
|
||||||
import nl.andrewlalis.util.Logging;
|
import nl.andrewlalis.util.Logging;
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.SessionFactory;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -51,12 +49,15 @@ public class Main {
|
||||||
"© Andrew Lalis (2018), All rights reserved.\n" +
|
"© Andrew Lalis (2018), All rights reserved.\n" +
|
||||||
"Program initialized.");
|
"Program initialized.");
|
||||||
|
|
||||||
SessionFactory factory = DbUtil.getSessionFactory();
|
GithubManager manager = new GithubManager();
|
||||||
Session session = factory.openSession();
|
StartView startView = new StartView(manager);
|
||||||
session.beginTransaction();
|
|
||||||
System.out.println(session.save(new Student(1, "a", "a@e.com", "git", null)));
|
// SessionFactory factory = DbUtil.getSessionFactory();
|
||||||
session.getTransaction().commit();
|
// Session session = factory.openSession();
|
||||||
session.close();
|
// session.beginTransaction();
|
||||||
|
// System.out.println(session.save(new Student(1, "a", "a@e.com", "git", null)));
|
||||||
|
// session.getTransaction().commit();
|
||||||
|
// session.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.command;
|
package nl.andrewlalis.command;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.executables.ExecutableContext;
|
import nl.andrewlalis.command.executables.ExecutableContext;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.ui.control.command;
|
package nl.andrewlalis.command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classes which implement this interface tell that they may be 'executed', either via command-line, or through the use
|
* Classes which implement this interface tell that they may be 'executed', either via command-line, or through the use
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
import nl.andrewlalis.ui.view.dialogs.DefineTaTeamsDialog;
|
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
import nl.andrewlalis.ui.view.dialogs.DefineTaTeamsDialog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This executable is slightly different from the others, in that it opens up a user interface to make editing TA teams
|
* This executable is slightly different from the others, in that it opens up a user interface to make editing TA teams
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
import nl.andrewlalis.model.StudentTeam;
|
import nl.andrewlalis.model.StudentTeam;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.Executable;
|
import nl.andrewlalis.command.Executable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object to record a specific executable's execution context (args given), with the ability to re-run the executable
|
* An object to record a specific executable's execution context (args given), with the ability to re-run the executable
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
|
import nl.andrewlalis.command.Executable;
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
import nl.andrewlalis.ui.control.command.Executable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an executable which interacts with github, and therefore needs access to a Github
|
* Represents an executable which interacts with github, and therefore needs access to a Github
|
|
@ -1,7 +1,7 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
|
import nl.andrewlalis.command.Executable;
|
||||||
import nl.andrewlalis.model.error.Error;
|
import nl.andrewlalis.model.error.Error;
|
||||||
import nl.andrewlalis.ui.control.command.Executable;
|
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
import org.kohsuke.github.GHRepository;
|
import org.kohsuke.github.GHRepository;
|
|
@ -1,7 +1,7 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
|
import nl.andrewlalis.command.Executable;
|
||||||
import nl.andrewlalis.model.StudentTeam;
|
import nl.andrewlalis.model.StudentTeam;
|
||||||
import nl.andrewlalis.ui.control.command.Executable;
|
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
import nl.andrewlalis.util.FileUtils;
|
import nl.andrewlalis.util.FileUtils;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.ui.control.command.executables;
|
package nl.andrewlalis.command.executables;
|
||||||
|
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
import nl.andrewlalis.model.StudentTeam;
|
import nl.andrewlalis.model.StudentTeam;
|
|
@ -31,6 +31,7 @@ public class GithubManager {
|
||||||
private GitHub github;
|
private GitHub github;
|
||||||
private GHOrganization organization;
|
private GHOrganization organization;
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
|
private String organizationName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger for outputting debug info.
|
* The logger for outputting debug info.
|
||||||
|
@ -40,14 +41,82 @@ public class GithubManager {
|
||||||
logger.setParent(Logger.getGlobal());
|
logger.setParent(Logger.getGlobal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty github manager, which at this point, essentially just allocates the object in memory.
|
||||||
|
*/
|
||||||
|
public GithubManager() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public GithubManager(String organizationName, String accessToken) {
|
public GithubManager(String organizationName, String accessToken) {
|
||||||
|
this.organizationName = organizationName;
|
||||||
this.accessToken = accessToken;
|
this.accessToken = accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the organization that this manager manages.
|
||||||
|
* @return The Organization object that this manager was constructed for.
|
||||||
|
* @throws IOException If the organization does not exist or some other error occurs.
|
||||||
|
*/
|
||||||
|
private GHOrganization getOrganization() throws IOException {
|
||||||
|
if (this.github == null || this.organization == null) {
|
||||||
|
this.github = GitHub.connectUsingOAuth(this.accessToken);
|
||||||
|
this.organization = this.github.getOrganization(this.organizationName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the manager is currently connected to github with the current organization name and access token.
|
||||||
|
* @return True if the manager is connected, or false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean validate() {
|
||||||
try {
|
try {
|
||||||
this.github = GitHub.connectUsingOAuth(accessToken);
|
this.organization = this.getOrganization();
|
||||||
this.organization = this.github.getOrganization(organizationName);
|
return this.organization != null;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.severe("Unable to make a GithubManager with organization name: " + organizationName + " and access token: " + accessToken);
|
return false;
|
||||||
e.printStackTrace();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrganizationName(String name) {
|
||||||
|
this.organizationName = name;
|
||||||
|
this.github = null;
|
||||||
|
this.organization = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessToken(String token) {
|
||||||
|
this.accessToken = token;
|
||||||
|
this.github = null;
|
||||||
|
this.organization = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a repository exists in the current organization.
|
||||||
|
* @param repoName The name of the repository.
|
||||||
|
* @return True if the repository exists, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean repoExists(String repoName) {
|
||||||
|
try {
|
||||||
|
GHRepository repo = this.getOrganization().getRepository(repoName);
|
||||||
|
return repo != null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a team exists in the current organization.
|
||||||
|
* @param teamName The name of the team.
|
||||||
|
* @return True if the team exists, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean teamExists(String teamName) {
|
||||||
|
try {
|
||||||
|
GHTeam team = this.getOrganization().getTeamByName(teamName);
|
||||||
|
return team != null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +128,7 @@ public class GithubManager {
|
||||||
public List<GHRepository> listReposWithPrefix(String substring) {
|
public List<GHRepository> listReposWithPrefix(String substring) {
|
||||||
List<GHRepository> repos = new ArrayList<>();
|
List<GHRepository> repos = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
List<GHRepository> allRepos = this.organization.listRepositories().asList();
|
List<GHRepository> allRepos = this.getOrganization().listRepositories().asList();
|
||||||
for (GHRepository repo : allRepos) {
|
for (GHRepository repo : allRepos) {
|
||||||
if (repo.getName().contains(substring)) {
|
if (repo.getName().contains(substring)) {
|
||||||
repos.add(repo);
|
repos.add(repo);
|
||||||
|
@ -81,7 +150,7 @@ public class GithubManager {
|
||||||
public GHRepository getRepository(String name) {
|
public GHRepository getRepository(String name) {
|
||||||
System.out.println(name);
|
System.out.println(name);
|
||||||
try {
|
try {
|
||||||
return this.organization.getRepository(name);
|
return this.getOrganization().getRepository(name);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.severe("No repository with name: " + name + " exists.");
|
logger.severe("No repository with name: " + name + " exists.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -97,7 +166,7 @@ public class GithubManager {
|
||||||
List<TATeam> teams = new ArrayList<>();
|
List<TATeam> teams = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
Random rand = new Random();
|
Random rand = new Random();
|
||||||
for (Map.Entry<String, GHTeam> entry : this.organization.getTeams().entrySet()) {
|
for (Map.Entry<String, GHTeam> entry : this.getOrganization().getTeams().entrySet()) {
|
||||||
TATeam team = new TATeam(entry.getKey(), entry.getValue().getId());
|
TATeam team = new TATeam(entry.getKey(), entry.getValue().getId());
|
||||||
team.setGithubTeam(entry.getValue());
|
team.setGithubTeam(entry.getValue());
|
||||||
for (GHUser user : entry.getValue().listMembers().asList()) {
|
for (GHUser user : entry.getValue().listMembers().asList()) {
|
||||||
|
@ -119,7 +188,7 @@ public class GithubManager {
|
||||||
public List<TeachingAssistant> getMembers() {
|
public List<TeachingAssistant> getMembers() {
|
||||||
List<TeachingAssistant> teachingAssistants = new ArrayList<>();
|
List<TeachingAssistant> teachingAssistants = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
for (GHUser member : this.organization.listMembers().asList()) {
|
for (GHUser member : this.getOrganization().listMembers().asList()) {
|
||||||
teachingAssistants.add(new TeachingAssistant(-1, member.getName(), member.getEmail(), member.getLogin()));
|
teachingAssistants.add(new TeachingAssistant(-1, member.getName(), member.getEmail(), member.getLogin()));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -137,9 +206,9 @@ public class GithubManager {
|
||||||
* @throws IOException If an HTTP request failed.
|
* @throws IOException If an HTTP request failed.
|
||||||
*/
|
*/
|
||||||
public void setupAssignmentsRepo(String assignmentsRepoName, String description, String allTeachingAssistants) throws IOException {
|
public void setupAssignmentsRepo(String assignmentsRepoName, String description, String allTeachingAssistants) throws IOException {
|
||||||
GHTeam team = this.organization.getTeamByName(allTeachingAssistants);
|
GHTeam team = this.getOrganization().getTeamByName(allTeachingAssistants);
|
||||||
// Check if the repository already exists.
|
// Check if the repository already exists.
|
||||||
GHRepository existingRepo = this.organization.getRepository(assignmentsRepoName);
|
GHRepository existingRepo = this.getOrganization().getRepository(assignmentsRepoName);
|
||||||
if (existingRepo != null) {
|
if (existingRepo != null) {
|
||||||
existingRepo.delete();
|
existingRepo.delete();
|
||||||
logger.fine("Deleted pre-existing assignments repository.");
|
logger.fine("Deleted pre-existing assignments repository.");
|
||||||
|
@ -174,9 +243,10 @@ public class GithubManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GHRepository repo = this.createRepository(team.generateUniqueName(prefix), taTeam.getGithubTeam(), team.generateRepoDescription(), false, true, true);
|
GHRepository repo;
|
||||||
|
try {
|
||||||
if (repo == null) {
|
repo = this.createRepository(team.generateUniqueName(prefix), taTeam.getGithubTeam(), team.generateRepoDescription(), false, true, true);
|
||||||
|
} catch (IOException e) {
|
||||||
logger.severe("Repository for student team " + team.getNumber() + " could not be created.");
|
logger.severe("Repository for student team " + team.getNumber() + " could not be created.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -195,17 +265,22 @@ public class GithubManager {
|
||||||
* @param substring The substring which repository names should contain to be deleted.
|
* @param substring The substring which repository names should contain to be deleted.
|
||||||
*/
|
*/
|
||||||
public void deleteAllRepositories(String substring) {
|
public void deleteAllRepositories(String substring) {
|
||||||
List<GHRepository> repositories = this.organization.listRepositories().asList();
|
try {
|
||||||
for (GHRepository repo : repositories) {
|
List<GHRepository> repositories = this.getOrganization().listRepositories().asList();
|
||||||
if (repo.getName().contains(substring)) {
|
for (GHRepository repo : repositories) {
|
||||||
try {
|
if (repo.getName().contains(substring)) {
|
||||||
repo.delete();
|
try {
|
||||||
logger.info("Deleted repository: " + repo.getName());
|
repo.delete();
|
||||||
} catch (IOException e) {
|
logger.info("Deleted repository: " + repo.getName());
|
||||||
logger.severe("Could not delete repository: " + repo.getName());
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.severe("Could not delete repository: " + repo.getName());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Could not get Organization for listing repositories.");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,11 +289,16 @@ public class GithubManager {
|
||||||
* @param sub Any repository containing this substring will be archived.
|
* @param sub Any repository containing this substring will be archived.
|
||||||
*/
|
*/
|
||||||
public void archiveAllRepositories(String sub) {
|
public void archiveAllRepositories(String sub) {
|
||||||
List<GHRepository> repositories = this.organization.listRepositories().asList();
|
try {
|
||||||
for (GHRepository repo : repositories) {
|
List<GHRepository> repositories = this.getOrganization().listRepositories().asList();
|
||||||
if (repo.getName().contains(sub)) {
|
for (GHRepository repo : repositories) {
|
||||||
archiveRepository(repo);
|
if (repo.getName().contains(sub)) {
|
||||||
|
archiveRepository(repo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Could not get Organization for listing repositories.");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,25 +419,20 @@ public class GithubManager {
|
||||||
* @param hasWiki Whether the repo has a wiki enabled.
|
* @param hasWiki Whether the repo has a wiki enabled.
|
||||||
* @param hasIssues Whether the repo has issues enabled.
|
* @param hasIssues Whether the repo has issues enabled.
|
||||||
* @param isPrivate Whether or not the repository is private.
|
* @param isPrivate Whether or not the repository is private.
|
||||||
* @return The repository that was created, or null if it could not be created.
|
* @return The repository that was created.
|
||||||
|
* @throws IOException If an exception occurred while sending a request.
|
||||||
*/
|
*/
|
||||||
private GHRepository createRepository(String name, GHTeam taTeam, String description, boolean hasWiki, boolean hasIssues, boolean isPrivate){
|
private GHRepository createRepository(String name, GHTeam taTeam, String description, boolean hasWiki, boolean hasIssues, boolean isPrivate) throws IOException {
|
||||||
try {
|
GHCreateRepositoryBuilder builder = this.getOrganization().createRepository(name);
|
||||||
GHCreateRepositoryBuilder builder = this.organization.createRepository(name);
|
builder.team(taTeam);
|
||||||
builder.team(taTeam);
|
builder.wiki(hasWiki);
|
||||||
builder.wiki(hasWiki);
|
builder.issues(hasIssues);
|
||||||
builder.issues(hasIssues);
|
builder.description(description);
|
||||||
builder.description(description);
|
builder.gitignoreTemplate("Java");
|
||||||
builder.gitignoreTemplate("Java");
|
builder.private_(isPrivate);
|
||||||
builder.private_(isPrivate);
|
GHRepository repo = builder.create();
|
||||||
GHRepository repo = builder.create();
|
logger.fine("Created repository: " + repo.getName());
|
||||||
logger.fine("Created repository: " + repo.getName());
|
return repo;
|
||||||
return repo;
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.severe("Could not create repository: " + name);
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package nl.andrewlalis.model;
|
|
||||||
|
|
||||||
public abstract class DatabaseObject {
|
|
||||||
|
|
||||||
public abstract DatabaseObject retrieve();
|
|
||||||
|
|
||||||
public abstract boolean store();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nl.andrewlalis.ui.control.listeners;
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.ui.view.InitializerApp;
|
import nl.andrewlalis.ui.view.InitializerApp;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package nl.andrewlalis.ui.control.listeners;
|
||||||
|
|
||||||
|
import nl.andrewlalis.ui.view.AbstractView;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ViewChangeListener is attached to buttons which should change the view to a new view. With this listener, one
|
||||||
|
* needs to simply give the previous view, and the next view, and
|
||||||
|
*/
|
||||||
|
public class ViewChangeListener implements ActionListener {
|
||||||
|
|
||||||
|
protected AbstractView previousView;
|
||||||
|
protected AbstractView newView;
|
||||||
|
|
||||||
|
public ViewChangeListener(AbstractView previousView, AbstractView newView) {
|
||||||
|
this.previousView = previousView;
|
||||||
|
this.newView = newView;
|
||||||
|
this.newView.addWindowListener(new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosing(WindowEvent windowEvent) {
|
||||||
|
back();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called just before the view is changed.
|
||||||
|
* @return True if the change should happen, or false if some validation or check prevents the user from moving to
|
||||||
|
* the next view.
|
||||||
|
*/
|
||||||
|
protected boolean beforeChange() {
|
||||||
|
// Child classes can implement extra behavior here.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines some default behavior for switching to a new view.
|
||||||
|
* @param actionEvent The event which triggered this action.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
if (this.beforeChange()) {
|
||||||
|
this.forward();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Goes to the new view, and hides the previous view.
|
||||||
|
*/
|
||||||
|
private void forward() {
|
||||||
|
this.previousView.setVisible(false);
|
||||||
|
this.newView.reset();
|
||||||
|
this.newView.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Goes 'back in time', or rather, hides the current view and moves back to the one which sent us here.
|
||||||
|
*/
|
||||||
|
private void back() {
|
||||||
|
this.previousView.reset();
|
||||||
|
this.previousView.setVisible(true);
|
||||||
|
this.newView.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package nl.andrewlalis.ui.control.listeners.create_assignments_view;
|
||||||
|
|
||||||
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
import nl.andrewlalis.ui.control.listeners.ViewChangeListener;
|
||||||
|
import nl.andrewlalis.ui.view.AbstractView;
|
||||||
|
import nl.andrewlalis.ui.view.CreateAssignmentsView;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for when the user clicks 'next' in the CreateAssignmentsView. This listener is responsible for checking that
|
||||||
|
* the user enters a correct repository name, or if not, asks if the user wishes to create the repository with that
|
||||||
|
* name.
|
||||||
|
*/
|
||||||
|
public class NextListener extends ViewChangeListener {
|
||||||
|
|
||||||
|
public NextListener(AbstractView previousView, AbstractView newView) {
|
||||||
|
super(previousView, newView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that the repository the user has entered exists in the organization.
|
||||||
|
* @return True if the repository exists, or if the user creates a repository with that name, or false if an
|
||||||
|
* Assignments repository was not created.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean beforeChange() {
|
||||||
|
CreateAssignmentsView assignmentsView = (CreateAssignmentsView) this.previousView;
|
||||||
|
String repoName = assignmentsView.getRepositoryName();
|
||||||
|
GithubManager manager = assignmentsView.getGithubManager();
|
||||||
|
if (manager.repoExists(repoName)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
int reply = JOptionPane.showConfirmDialog(
|
||||||
|
assignmentsView,
|
||||||
|
"The repository you gave does not exist.\nWould you like to create it?",
|
||||||
|
"Create new repository?",
|
||||||
|
JOptionPane.YES_NO_OPTION);
|
||||||
|
if (reply == JOptionPane.YES_OPTION) {
|
||||||
|
try {
|
||||||
|
assignmentsView.getGithubManager().setupAssignmentsRepo(repoName, "", this.getTeachingAssistantsTeamName());
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
JOptionPane.showMessageDialog(assignmentsView, "Could not create repository:\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTeachingAssistantsTeamName() {
|
||||||
|
String name = JOptionPane.showInputDialog(this.previousView, "Please enter (exactly) the name of Github team\nthat contains all teaching assistants.", "Select TA Team", JOptionPane.QUESTION_MESSAGE);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package nl.andrewlalis.ui.control.listeners.start_view;
|
||||||
|
|
||||||
|
import nl.andrewlalis.ui.control.listeners.ViewChangeListener;
|
||||||
|
import nl.andrewlalis.ui.view.AbstractView;
|
||||||
|
import nl.andrewlalis.ui.view.StartView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for when the user intends to create repositories for a new course.
|
||||||
|
*/
|
||||||
|
public class CreateAssignmentsRepoListener extends ViewChangeListener {
|
||||||
|
|
||||||
|
public CreateAssignmentsRepoListener(AbstractView previousView, AbstractView newView) {
|
||||||
|
super(previousView, newView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All that needs to be done here is check that the github manager can work with the given info.
|
||||||
|
* @return True if the github manager accepts the organization name and access token, false otherwise.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean beforeChange() {
|
||||||
|
StartView startView = (StartView) this.previousView;
|
||||||
|
startView.getGithubManager().setOrganizationName(startView.getOrganizationName());
|
||||||
|
startView.getGithubManager().setAccessToken(startView.getAccessToken());
|
||||||
|
return startView.getGithubManager().validate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package nl.andrewlalis.ui.view;
|
||||||
|
|
||||||
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All views in the application will extend from this view, as a means of simplifying and organizing how visual
|
||||||
|
* components are made.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractView extends JFrame {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GithubManager object which can be used to interact with github.
|
||||||
|
*/
|
||||||
|
private GithubManager githubManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the view by packing the content pane as it is defined by any child, and setting some generic swing
|
||||||
|
* values.
|
||||||
|
* @param title The window's title.
|
||||||
|
* @param startVisible Whether or not to start the view as visible.
|
||||||
|
* @param defaultCloseOperation What to do when the user closes the window.
|
||||||
|
* @param preferredSize The preferred size of the view.
|
||||||
|
*/
|
||||||
|
AbstractView(String title, boolean startVisible, int defaultCloseOperation, Dimension preferredSize, GithubManager githubManager) {
|
||||||
|
super(title);
|
||||||
|
this.githubManager = githubManager;
|
||||||
|
this.setContentPane(this.buildContentPane());
|
||||||
|
this.setDefaultCloseOperation(defaultCloseOperation);
|
||||||
|
if (preferredSize != null) {
|
||||||
|
this.setSize(preferredSize);
|
||||||
|
}
|
||||||
|
this.setLocationRelativeTo(null);
|
||||||
|
this.pack();
|
||||||
|
this.setVisible(startVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs this view. Child classes will define how the content pane is constructed by returning that content
|
||||||
|
* pane here.
|
||||||
|
* @return The content pane containing the view to be rendered.
|
||||||
|
*/
|
||||||
|
protected abstract JPanel buildContentPane();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets this view and all form components within it. It is the responsibility of child classes to define how to
|
||||||
|
* reset themselves.
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
// Child classes can define custom behavior here.
|
||||||
|
}
|
||||||
|
|
||||||
|
public GithubManager getGithubManager() {
|
||||||
|
return githubManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a text input field panel.
|
||||||
|
* @param labelText The text for the label above the panel.
|
||||||
|
* @param textField A reference to the text field that is used in the panel.
|
||||||
|
* @return A JPanel containing the label and text field.
|
||||||
|
*/
|
||||||
|
final JPanel generateTextFieldPanel(String labelText, JTextField textField) {
|
||||||
|
JPanel newPanel = new JPanel(new BorderLayout());
|
||||||
|
newPanel.add(new JLabel(labelText), BorderLayout.NORTH);
|
||||||
|
newPanel.add(textField);
|
||||||
|
newPanel.setBorder(BorderFactory.createEmptyBorder(5, 2, 5, 2));
|
||||||
|
return newPanel;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package nl.andrewlalis.ui.view;
|
||||||
|
|
||||||
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
import nl.andrewlalis.ui.control.listeners.create_assignments_view.NextListener;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In this view, the user will enter the name of an assignments repository to use for the course, or allows the user to
|
||||||
|
* create a new one.
|
||||||
|
*
|
||||||
|
* Once the user is here, it is guaranteed that the github manager has been validated.
|
||||||
|
*/
|
||||||
|
public class CreateAssignmentsView extends AbstractView {
|
||||||
|
|
||||||
|
private JTextField repositoryNameField;
|
||||||
|
|
||||||
|
public CreateAssignmentsView(GithubManager manager) {
|
||||||
|
super("Create/Set Assignments Repository",
|
||||||
|
false,
|
||||||
|
DISPOSE_ON_CLOSE,
|
||||||
|
null,
|
||||||
|
manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRepositoryName() {
|
||||||
|
return this.repositoryNameField.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JPanel buildContentPane() {
|
||||||
|
JPanel contentPane = new JPanel();
|
||||||
|
|
||||||
|
contentPane.setLayout(new BorderLayout());
|
||||||
|
this.repositoryNameField = new JTextField();
|
||||||
|
contentPane.add(this.generateTextFieldPanel("Repository name:", this.repositoryNameField), BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JButton nextButton = new JButton("Next");
|
||||||
|
nextButton.addActionListener(new NextListener(this, new InputStudentsFileView(this.getGithubManager())));
|
||||||
|
contentPane.add(nextButton, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
return contentPane;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package nl.andrewlalis.ui.view;
|
package nl.andrewlalis.ui.view;
|
||||||
|
|
||||||
|
import nl.andrewlalis.command.CommandExecutor;
|
||||||
import nl.andrewlalis.model.Organization;
|
import nl.andrewlalis.model.Organization;
|
||||||
import nl.andrewlalis.ui.control.OutputTextHandler;
|
import nl.andrewlalis.ui.control.OutputTextHandler;
|
||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
|
|
||||||
import nl.andrewlalis.ui.control.listeners.*;
|
import nl.andrewlalis.ui.control.listeners.*;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -129,11 +129,6 @@ public class InitializerApp extends JFrame {
|
||||||
commonActionsPanel.add(this.generateButtonPanel("Delegate Student Teams", new DelegateStudentTeamsListener(this.executor, this)));
|
commonActionsPanel.add(this.generateButtonPanel("Delegate Student Teams", new DelegateStudentTeamsListener(this.executor, this)));
|
||||||
commonActionsPanel.add(this.generateButtonPanel("Generate Assignments Repo", new GenerateAssignmentsRepoListener(this.executor, this)));
|
commonActionsPanel.add(this.generateButtonPanel("Generate Assignments Repo", new GenerateAssignmentsRepoListener(this.executor, this)));
|
||||||
|
|
||||||
// TODO: Enable this once the define teams dialog is complete.
|
|
||||||
// JButton defineTaTeamsButton = new JButton("Define TA Teams");
|
|
||||||
// defineTaTeamsButton.addActionListener(new DefineTaTeamsListener(this.executor, this));
|
|
||||||
// commonActionsPanel.add(f);
|
|
||||||
|
|
||||||
commonActionsPanel.add(this.generateButtonPanel("Delete Repos", new DeleteReposListener(this.executor, this)));
|
commonActionsPanel.add(this.generateButtonPanel("Delete Repos", new DeleteReposListener(this.executor, this)));
|
||||||
|
|
||||||
// Extra panel to push buttons to the top.
|
// Extra panel to push buttons to the top.
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package nl.andrewlalis.ui.view;
|
||||||
|
|
||||||
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In this view, the user will select a file to read a list of students from, and generates the list of teams from that.
|
||||||
|
*/
|
||||||
|
public class InputStudentsFileView extends AbstractView {
|
||||||
|
|
||||||
|
InputStudentsFileView(GithubManager manager) {
|
||||||
|
super("Input Students CSV",
|
||||||
|
false,
|
||||||
|
DISPOSE_ON_CLOSE,
|
||||||
|
null,
|
||||||
|
manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JPanel buildContentPane() {
|
||||||
|
JPanel contentPane = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
JButton selectFileButton = new JButton("Select File");
|
||||||
|
contentPane.add(selectFileButton, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JButton doneButton = new JButton("Done");
|
||||||
|
contentPane.add(doneButton, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
return contentPane;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package nl.andrewlalis.ui.view;
|
||||||
|
|
||||||
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
import nl.andrewlalis.ui.control.listeners.start_view.CreateAssignmentsRepoListener;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* At this view, the user is asked to first enter the name of the organization, and the access token they created for
|
||||||
|
* their authenticated Github account.
|
||||||
|
*
|
||||||
|
* Then, the user must choose whether they are starting a new course setup, or managing an existing one.
|
||||||
|
*
|
||||||
|
* If they choose to start a new course, they are taken to the AssignmentsRepoView, otherwise if they want to manage
|
||||||
|
* an existing course, they are taken to the ManagementView.
|
||||||
|
*/
|
||||||
|
public class StartView extends AbstractView {
|
||||||
|
|
||||||
|
// Fields which hold information needed by the Github Manager.
|
||||||
|
private JTextField organizationNameField;
|
||||||
|
private JTextField accessTokenField;
|
||||||
|
|
||||||
|
public StartView(GithubManager githubManager) {
|
||||||
|
super("Github Initializer Startup",
|
||||||
|
true,
|
||||||
|
DISPOSE_ON_CLOSE,
|
||||||
|
null,
|
||||||
|
githubManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrganizationName() {
|
||||||
|
return this.organizationNameField.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccessToken() {
|
||||||
|
return this.accessTokenField.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JPanel buildContentPane() {
|
||||||
|
JPanel contentPane = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel infoInputPanel = new JPanel();
|
||||||
|
infoInputPanel.setLayout(new BoxLayout(infoInputPanel, BoxLayout.PAGE_AXIS));
|
||||||
|
this.organizationNameField = new JTextField();
|
||||||
|
infoInputPanel.add(this.generateTextFieldPanel("Organization name:", this.organizationNameField));
|
||||||
|
this.accessTokenField = new JTextField();
|
||||||
|
infoInputPanel.add(this.generateTextFieldPanel("Access token:", this.accessTokenField));
|
||||||
|
|
||||||
|
JPanel buttonsPanel = new JPanel();
|
||||||
|
JButton assignmentsViewButton = new JButton("Start New Course");
|
||||||
|
assignmentsViewButton.addActionListener(new CreateAssignmentsRepoListener(this, new CreateAssignmentsView(this.getGithubManager())));
|
||||||
|
JButton managementViewButton = new JButton("Manage Existing Course");
|
||||||
|
|
||||||
|
buttonsPanel.add(assignmentsViewButton);
|
||||||
|
buttonsPanel.add(managementViewButton);
|
||||||
|
|
||||||
|
contentPane.add(infoInputPanel, BorderLayout.CENTER);
|
||||||
|
contentPane.add(buttonsPanel, BorderLayout.SOUTH);
|
||||||
|
return contentPane;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
INSERT INTO person_types (id, name)
|
|
||||||
VALUES (0, 'student'),
|
|
||||||
(1, 'teaching-assistant'),
|
|
||||||
(2, 'professor');
|
|
||||||
|
|
||||||
INSERT INTO team_types (id, name)
|
|
||||||
VALUES (0, 'student_team'),
|
|
||||||
(1, 'teaching_assistant_team'),
|
|
||||||
(2, 'all_teaching_assistants'),
|
|
||||||
(3, 'none');
|
|
||||||
|
|
||||||
INSERT INTO teams (id, team_type_id)
|
|
||||||
VALUES (1000000, 3), -- None team for all students or TA's without a team.
|
|
||||||
(1000001, 2); -- Team for all teaching assistants.
|
|
||||||
|
|
||||||
INSERT INTO error_types (id, name)
|
|
||||||
VALUES (0, 'team_error'),
|
|
||||||
(1, 'person_error'),
|
|
||||||
(2, 'system_error');
|
|
|
@ -1,153 +0,0 @@
|
||||||
PRAGMA foreign_keys = TRUE;
|
|
||||||
PRAGMA writable_schema = 1;
|
|
||||||
DELETE FROM sqlite_master WHERE type IN ('table', 'index', 'trigger');
|
|
||||||
PRAGMA writable_schema = 0;
|
|
||||||
VACUUM;
|
|
||||||
|
|
||||||
-- Basic schema design.
|
|
||||||
CREATE TABLE IF NOT EXISTS person_types (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL UNIQUE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS persons (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
email_address TEXT NOT NULL,
|
|
||||||
github_username TEXT NOT NULL UNIQUE,
|
|
||||||
person_type_id INTEGER NOT NULL,
|
|
||||||
team_id INTEGER NULL,
|
|
||||||
FOREIGN KEY (person_type_id)
|
|
||||||
REFERENCES person_types(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (team_id)
|
|
||||||
REFERENCES teams(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Team tables for all types of teams.
|
|
||||||
CREATE TABLE IF NOT EXISTS team_types (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL UNIQUE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS teams (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
team_type_id INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY (team_type_id)
|
|
||||||
REFERENCES team_types(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS team_members (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
team_id INTEGER NOT NULL,
|
|
||||||
person_id INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY (team_id)
|
|
||||||
REFERENCES teams(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (person_id)
|
|
||||||
REFERENCES persons(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE,
|
|
||||||
UNIQUE (team_id, person_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS teaching_assistant_teams (
|
|
||||||
team_id INTEGER PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL UNIQUE,
|
|
||||||
FOREIGN KEY (team_id)
|
|
||||||
REFERENCES teams(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS student_teams (
|
|
||||||
team_id INTEGER PRIMARY KEY,
|
|
||||||
repository_name TEXT,
|
|
||||||
teaching_assistant_team_id INTEGER,
|
|
||||||
FOREIGN KEY (team_id)
|
|
||||||
REFERENCES teams(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (teaching_assistant_team_id)
|
|
||||||
REFERENCES teaching_assistant_teams(team_id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Student-specific tables.
|
|
||||||
CREATE TABLE IF NOT EXISTS students (
|
|
||||||
person_id INTEGER PRIMARY KEY,
|
|
||||||
chose_partner INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY (person_id)
|
|
||||||
REFERENCES persons(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS student_preferred_partners (
|
|
||||||
student_id INTEGER PRIMARY KEY,
|
|
||||||
partner_id INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY (student_id)
|
|
||||||
REFERENCES students(person_id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE,
|
|
||||||
UNIQUE (student_id, partner_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- TeachingAssistant-specific tables.
|
|
||||||
CREATE TABLE IF NOT EXISTS teaching_assistants (
|
|
||||||
person_id INTEGER PRIMARY KEY,
|
|
||||||
FOREIGN KEY (person_id)
|
|
||||||
REFERENCES persons(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Error queue storage.
|
|
||||||
CREATE TABLE IF NOT EXISTS error_types (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL UNIQUE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS errors (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
error_type_id INTEGER NOT NULL,
|
|
||||||
message TEXT NOT NULL,
|
|
||||||
FOREIGN KEY (error_type_id)
|
|
||||||
REFERENCES error_types(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS team_errors (
|
|
||||||
error_id INTEGER PRIMARY KEY,
|
|
||||||
team_id INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY (error_id)
|
|
||||||
REFERENCES errors(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (team_id)
|
|
||||||
REFERENCES teams(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS person_errors (
|
|
||||||
error_id INTEGER PRIMARY KEY,
|
|
||||||
person_id INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY (error_id)
|
|
||||||
REFERENCES errors(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (person_id)
|
|
||||||
REFERENCES persons(id)
|
|
||||||
ON DELETE CASCADE
|
|
||||||
ON UPDATE CASCADE
|
|
||||||
);
|
|
Loading…
Reference in New Issue