diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 796413d..528cc73 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,8 +44,6 @@ jobs: QUARKUS_DATASOURCE_PASSWORD: ${{secrets.QUARKUS_DATASOURCE_PASSWORD}} QUARKUS_DATASOURCE_JDBC_URL: ${{secrets.QUARKUS_DATASOURCE_JDBC_URL}} - FRONTEND_USERNAME: ${{secrets.FRONTEND_USERNAME}} - FRONTEND_PASSWORD: ${{secrets.FRONTEND_PASSWORD}} deploy: needs: build diff --git a/backend/og-pom.txt b/backend/og-pom.txt new file mode 100644 index 0000000..80c2bf8 --- /dev/null +++ b/backend/og-pom.txt @@ -0,0 +1,124 @@ + + + 4.0.0 + org.acme + backend + 1.0.0-SNAPSHOT + + + 3.13.0 + 21 + UTF-8 + UTF-8 + quarkus-bom + io.quarkus.platform + 3.13.3 + true + 3.2.5 + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-rest + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + native-image-agent + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + true + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + native + + + + false + true + + + + diff --git a/backend/pom.xml b/backend/pom.xml index 0dc9d4c..e7a8180 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -98,7 +98,11 @@ io.quarkus - quarkus-security-jpa + quarkus-smallrye-metrics + + + io.quarkus + quarkus-narayana-jta diff --git a/backend/src/main/java/org/acme/TimetableResource.java b/backend/src/main/java/org/acme/TimetableResource.java new file mode 100644 index 0000000..2d73625 --- /dev/null +++ b/backend/src/main/java/org/acme/TimetableResource.java @@ -0,0 +1,230 @@ +package org.acme; + +import ai.timefold.solver.core.api.solver.SolverManager; +import io.smallrye.mutiny.Uni; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import org.acme.domain.Room; +import org.acme.domain.Student; +import org.acme.domain.Timetable; +import org.acme.domain.Unit; + +import java.time.DayOfWeek; +import java.time.Duration; +import java.time.LocalTime; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import java.util.UUID; + +/** + * Entry to the timetabling program. + * Receives a timetabling problem and outputs the solution + * with the best optimised scores according to the provided constraints. + * + * @author Jet Edge + */ +@Path("/timetabling") +public class TimetableResource { + + @Inject + SolverManager solverManager; + + @POST + @Transactional + public Timetable handleRequest(Timetable problem) throws ExecutionException, InterruptedException { + UUID uuid = UUID.randomUUID(); + String uuidAsString = uuid.toString(); + + System.out.println("Your UUID is: " + uuidAsString); + String name = "Job" + uuidAsString; + + findByCampusAndDelete(problem.campusName); + + // generate solution timetable with TimeFold Solver + Timetable solution = solverManager.solve(name, problem).getFinalBestSolution(); + + // store the solution timetable to the database + solution.persist(); + + return solution; + } + + @Path("/view") + @GET + @Produces(MediaType.APPLICATION_JSON) + public List view() { + return Timetable.listAll(); + } + + + /** + * Takes a list of Units as input to updates exisiting timetable once users + * make drag-and-drop modifications in frontend + * + * @param updatedUnits List of all Unit updates + * @return A Response object indicating status + */ + @Path("/update") + @PUT + @Transactional + @Consumes(MediaType.APPLICATION_JSON) + public Response timetableUpdate(List updatedUnits) { + List dbUnits = Unit.listAll(); + for (Unit updatedUnit : updatedUnits) { + if (unitUpdate(updatedUnit, dbUnits) == null) { + return Response.serverError().build(); + } + } + return Response.ok().build(); + } + + + /** + * Update the time/location of a unit + * + * @param updatedUnit Unit object with updated time/location + * @param dbUnits List of all Unit objects in the database + * @return The updated Unit, null otherwise + */ + @PUT + @Transactional + @Consumes(MediaType.APPLICATION_JSON) + public Unit unitUpdate(Unit updatedUnit, List dbUnits) { + + // find existing Unit obj in db by unitId + for (Unit unit : dbUnits) { + if (updatedUnit.unitId == unit.unitId) { + assert(unit.isPersistent()); + // update day of week + unit.dayOfWeek = updatedUnit.dayOfWeek; + // update startTime + unit.startTime = updatedUnit.startTime; + // if room is different + if (unit.room.roomCode != updatedUnit.room.roomCode + || !unit.room.buildingId.equals(updatedUnit.room.buildingId)) { + // update room + Room newRoom; + if ((newRoom = findRoom(updatedUnit.room)) == null) { + throw new WebApplicationException("Room with building ID " + updatedUnit.room.buildingId + ", and room code " + updatedUnit.room.roomCode + " not found", 404); + } + unit.room = newRoom; + } + return unit; + } + } + return null; + } + + /** + * Find existing Room object inside the database with + * desired buildingId and roomCode + * + * @param inputRoom Room object with buildingId and roomCode of desired Room + * @return Room object meeting the input criteria, null otherwise + */ + public Room findRoom(Room inputRoom) { + List rooms = Room.listAll(); + for (Room room : rooms) { + if (room.roomCode.equals(inputRoom.roomCode) + && room.buildingId.equals(inputRoom.buildingId)) { + assert(room.isPersistent()); + return room; + } + } + return null; + } + + public void findByCampusAndDelete(String campusName) { + List timetables = Timetable.listAll(); + for (Timetable timetable : timetables) { + if (campusName.equals(timetable.campusName)) { + timetable.delete(); + } + } + } + + @GET + @Transactional + @Produces(MediaType.APPLICATION_JSON) + public Timetable solveExample() throws ExecutionException, InterruptedException { + + Student a = new Student("a"); + Student b = new Student("b"); + Student c = new Student("c"); + Student d = new Student("d"); + Student e = new Student("e"); + Student f = new Student("f"); + Student g = new Student("g"); + Student h = new Student("h"); + Student i = new Student("i"); + + Room r1 = new Room("Room1", "building A", "campus A", 2, true); + Room r2 = new Room("Room2", "building B", "campus A", 4, false); + Room r3 = new Room("Room3", "building A", "campus B", 4, false); + + Unit u1 = new Unit(1, "1", "Course A", Duration.ofHours(2), List.of(a, b), true); + Unit u2 = new Unit(2, "2", "Course A", Duration.ofHours(2), List.of(a, c, d, e), true); + Unit u3 = new Unit(3, "3", "Course B", Duration.ofHours(2), List.of(f, g, h, i), false); + Unit u4 = new Unit(4, "4", "Course C", Duration.ofHours(2), List.of(a, b), false); + + var problem = new Timetable("Campus A", + List.of( + u1, u2, u3, u4 +// new Unit(5, "5", Duration.ofHours(2), List.of(c, d, e)), +// new Unit(6, "6", Duration.ofHours(2), List.of(f, g, h, i)) + ), + + List.of( + DayOfWeek.MONDAY, + DayOfWeek.TUESDAY, + DayOfWeek.WEDNESDAY +// DayOfWeek.THURSDAY, +// DayOfWeek.FRIDAY + ), + + List.of( + LocalTime.of(15, 0) +// LocalTime.of(17, 0) +// LocalTime.of(16,0), +// LocalTime.of(23,0) + ), + List.of(r1, r2, r3) + ); + + /* + * During this solving phase, new Unit objects will be created with the + * alloted date and Room assignment. + * + * Currently, the 'old' Unit objects in the 'problem' variable and the + * 'new' Unit objects in the 'solution' variable are stored as different + * Units in the database due to our inability to control the behaviour + * of solverManager.solve + * + * i.e. after solving, there will be 2 copies of each Unit in the + * database, where the 'old' Unit has the list of students but no + * timetable assignment, while the 'new' Unit does not have the list + * of students enrolled, but does have the assigned date and room + */ + + findByCampusAndDelete(problem.campusName); + + Timetable solution = solverManager.solve("job 1", problem).getFinalBestSolution(); + + solution.persist(); + // saves the solution timetable and all related entities to database + + return solution; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/org/acme/domain/Room.java b/backend/src/main/java/org/acme/domain/Room.java index 1d063ee..883e39e 100644 --- a/backend/src/main/java/org/acme/domain/Room.java +++ b/backend/src/main/java/org/acme/domain/Room.java @@ -1,13 +1,18 @@ package org.acme.domain; -import ai.timefold.solver.core.api.domain.lookup.PlanningId; +import java.util.ArrayList; +import java.util.List; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.*; -import java.util.ArrayList; -import java.util.List; +import ai.timefold.solver.core.api.domain.lookup.PlanningId; +import io.quarkus.hibernate.orm.panache.PanacheEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; /** * Represents a room. @@ -16,7 +21,7 @@ */ @Entity public class Room extends PanacheEntity { - + @PlanningId public String roomCode; @@ -50,11 +55,11 @@ public Room() { /** * Creates a room with its ID and capacity. * - * @param id The room’s id. - * @param buildingId The building that the room belongs to. - * @param campus The campus that the room belongs to. - * @param capacity The room's capacity. - * @param isLab Whether the room is a laboratory. + * @param id The room’s id. + * @param buildingId The building that the room belongs to. + * @param buildingId The campus that the room belongs to. + * @param capacity The room's capacity. + * @param isLab Whether the room is a laboratory. */ public Room(String id, String buildingId, String campus, int capacity, boolean isLab) { this.roomCode = id; diff --git a/backend/src/main/java/org/acme/rest/RoomResource.java b/backend/src/main/java/org/acme/domain/RoomResource.java similarity index 76% rename from backend/src/main/java/org/acme/rest/RoomResource.java rename to backend/src/main/java/org/acme/domain/RoomResource.java index f31b2af..c86a1a9 100644 --- a/backend/src/main/java/org/acme/rest/RoomResource.java +++ b/backend/src/main/java/org/acme/domain/RoomResource.java @@ -1,16 +1,17 @@ -package org.acme.rest; +package org.acme.domain; + +import java.util.List; -import jakarta.annotation.security.RolesAllowed; import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -import org.acme.domain.Room; - -import java.util.List; @Path("/rooms") -@RolesAllowed({"user"}) public class RoomResource { @GET diff --git a/backend/src/main/java/org/acme/domain/Student.java b/backend/src/main/java/org/acme/domain/Student.java index 7804ba7..614513a 100644 --- a/backend/src/main/java/org/acme/domain/Student.java +++ b/backend/src/main/java/org/acme/domain/Student.java @@ -1,30 +1,36 @@ package org.acme.domain; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.*; - import java.util.ArrayList; import java.util.List; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.quarkus.hibernate.orm.panache.PanacheEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; + /** * Represents a student. * * @author Jet Edge */ @Entity -public class Student extends PanacheEntity { +public class Student extends PanacheEntity{ public String name; @JsonIgnoreProperties("students") @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable( - name = "student_unit", - joinColumns = @JoinColumn(name = "student_id"), - inverseJoinColumns = @JoinColumn(name = "unit_id") + name = "student_unit", + joinColumns = @JoinColumn(name = "student_id"), + inverseJoinColumns = @JoinColumn(name = "unit_id") ) @JsonIgnore public List units = new ArrayList(); diff --git a/backend/src/main/java/org/acme/rest/StudentResource.java b/backend/src/main/java/org/acme/domain/StudentResource.java similarity index 76% rename from backend/src/main/java/org/acme/rest/StudentResource.java rename to backend/src/main/java/org/acme/domain/StudentResource.java index 7c75d27..996d015 100644 --- a/backend/src/main/java/org/acme/rest/StudentResource.java +++ b/backend/src/main/java/org/acme/domain/StudentResource.java @@ -1,12 +1,15 @@ -package org.acme.rest; +package org.acme.domain; + +import java.util.List; import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -import org.acme.domain.Student; - -import java.util.List; @Path("/students") public class StudentResource { diff --git a/backend/src/main/java/org/acme/domain/Timetable.java b/backend/src/main/java/org/acme/domain/Timetable.java index 325b0ea..07a139d 100644 --- a/backend/src/main/java/org/acme/domain/Timetable.java +++ b/backend/src/main/java/org/acme/domain/Timetable.java @@ -6,16 +6,23 @@ import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty; import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; import ai.timefold.solver.core.api.score.buildin.hardsoft.HardSoftScore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.*; +import jakarta.persistence.CascadeType; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; import java.time.DayOfWeek; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * Represents a timetable, the solution from the program. * @@ -37,16 +44,16 @@ public class Timetable extends PanacheEntity { /* * Rooms can belong to multiple timetables because timetables are generated - * on a per-campus basis, and although each room can only belong to one + * on a per-campus basis, and although each room can only belong to one * campus, the user may choose to generate multiple timetables for each * campus, hence the many-to-many relationship */ @JsonIgnoreProperties("timetables") @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable( - name = "room_timetable", - joinColumns = @JoinColumn(name = "timetable_id"), - inverseJoinColumns = @JoinColumn(name = "room_id") + name = "room_timetable", + joinColumns = @JoinColumn(name = "timetable_id"), + inverseJoinColumns = @JoinColumn(name = "room_id") ) @ProblemFactCollectionProperty @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @@ -61,9 +68,9 @@ public class Timetable extends PanacheEntity { @JsonIgnoreProperties("timetables") @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable( - name = "unit_timetable", - joinColumns = @JoinColumn(name = "timetable_id"), - inverseJoinColumns = @JoinColumn(name = "unit_id") + name = "unit_timetable", + joinColumns = @JoinColumn(name = "timetable_id"), + inverseJoinColumns = @JoinColumn(name = "unit_id") ) @PlanningEntityCollectionProperty public List units; diff --git a/backend/src/main/java/org/acme/domain/Unit.java b/backend/src/main/java/org/acme/domain/Unit.java index eb4cef6..8bc6d00 100644 --- a/backend/src/main/java/org/acme/domain/Unit.java +++ b/backend/src/main/java/org/acme/domain/Unit.java @@ -3,10 +3,14 @@ import ai.timefold.solver.core.api.domain.entity.PlanningEntity; import ai.timefold.solver.core.api.domain.lookup.PlanningId; import ai.timefold.solver.core.api.domain.variable.PlanningVariable; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.*; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Transient; import java.time.DayOfWeek; import java.time.Duration; @@ -14,6 +18,9 @@ import java.util.ArrayList; import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + /** * Represents a unit. * @@ -48,8 +55,8 @@ public class Unit extends PanacheEntity { /* * currently each unit only has 1 'slot' on the timetable, so it can only - * be associated with one room, but in the final product, we would most - * likely have to change this to a many-to-many relationship + * be associated with one room, but in the final product, we would most + * likely have to change this to a many-to-many relationship * i.e. list of Rooms, because we might want to separate lecture/tutorial * etc. */ @@ -121,7 +128,7 @@ public Unit(int unitID, String name, String course, Duration duration, List students, boolean wantsLab, Room room) { this.unitId = unitID; @@ -187,7 +194,7 @@ public List getStudents() { public void setStudents(List students) { this.students = students; - this.setStudentsUnits(); + this.setStudentsUnits();; } /** diff --git a/backend/src/main/java/org/acme/rest/UnitResource.java b/backend/src/main/java/org/acme/domain/UnitResource.java similarity index 76% rename from backend/src/main/java/org/acme/rest/UnitResource.java rename to backend/src/main/java/org/acme/domain/UnitResource.java index 80b269b..8455d46 100644 --- a/backend/src/main/java/org/acme/rest/UnitResource.java +++ b/backend/src/main/java/org/acme/domain/UnitResource.java @@ -1,16 +1,17 @@ -package org.acme.rest; +package org.acme.domain; + +import java.util.List; -import jakarta.annotation.security.RolesAllowed; import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -import org.acme.domain.Unit; - -import java.util.List; @Path("/units") -@RolesAllowed({"user"}) public class UnitResource { @GET @Produces(MediaType.APPLICATION_JSON) diff --git a/backend/src/main/java/org/acme/security/jpa/Startup.java b/backend/src/main/java/org/acme/security/jpa/Startup.java deleted file mode 100644 index 53d4fa3..0000000 --- a/backend/src/main/java/org/acme/security/jpa/Startup.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.acme.security.jpa; - -import io.quarkus.runtime.StartupEvent; -import jakarta.enterprise.event.Observes; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import jakarta.transaction.Transactional; -import org.eclipse.microprofile.config.Config; - -@Singleton -public class Startup { - @Inject - Config config; - - @Transactional - public void loadUsers(@Observes StartupEvent evt) { - String username = config.getValue("frontend.username", String.class); - String password = config.getValue("frontend.password", String.class); - - // reset and load user - User.deleteAll(); - User.add(username, password, "user"); - } -} \ No newline at end of file diff --git a/backend/src/main/java/org/acme/security/jpa/User.java b/backend/src/main/java/org/acme/security/jpa/User.java deleted file mode 100644 index d2f384b..0000000 --- a/backend/src/main/java/org/acme/security/jpa/User.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.acme.security.jpa; - -import io.quarkus.elytron.security.common.BcryptUtil; -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import io.quarkus.security.jpa.Password; -import io.quarkus.security.jpa.Roles; -import io.quarkus.security.jpa.UserDefinition; -import io.quarkus.security.jpa.Username; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; - -@Entity -@Table(name = "frontend_user") -@UserDefinition -public class User extends PanacheEntity { - @Username - public String username; - @Password - public String password; - @Roles - public String role; - - /** - * Adds a new user to the database - * - * @param username the username - * @param password the unencrypted password (it is encrypted with bcrypt) - * @param role the comma-separated roles - */ - public static void add(String username, String password, String role) { - User user = new User(); - user.username = username; - user.password = BcryptUtil.bcryptHash(password); - user.role = role; - user.persist(); - } -} \ No newline at end of file diff --git a/backend/src/main/java/org/acme/security/jpa/UserResource.java b/backend/src/main/java/org/acme/security/jpa/UserResource.java deleted file mode 100644 index d22b125..0000000 --- a/backend/src/main/java/org/acme/security/jpa/UserResource.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.acme.security.jpa; - -import jakarta.annotation.security.RolesAllowed; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.SecurityContext; - -@Path("/login") -public class UserResource { - - @GET - @RolesAllowed({"user"}) - public String me(@Context SecurityContext securityContext) { - return securityContext.getUserPrincipal().getName(); - } -} \ No newline at end of file diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index ea01c7f..cf27fd9 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -2,9 +2,7 @@ quarkus.http.port=${PORT:8080} # The solver runs only for 5 seconds to avoid a HTTP timeout in this simple implementation. # It's recommended to run for at least 5 minutes ("5m") otherwise. - -quarkus.timefold.solver.termination.spent-limit=15s - +quarkus.timefold.solver.termination.spent-limit=60s quarkus.http.cors=true quarkus.http.cors.origins=* quarkus.http.cors.methods=GET,POST,PUT,DELETE,OPTIONS @@ -17,7 +15,7 @@ quarkus.datasource.password = ${QUARKUS_DATASOURCE_PASSWORD} quarkus.datasource.jdbc.url = ${QUARKUS_DATASOURCE_JDBC_URL} # drop and create the database at startup (use `update` to only update the schema) -quarkus.hibernate-orm.database.generation = update +quarkus.hibernate-orm.database.generation = create-drop # transaction timeout quarkus.transaction-manager.default-transaction-timeout=320s @@ -74,7 +72,3 @@ quarkus.log.file.enable=true quarkus.log.file.path=logs/quarkus.log quarkus.log.file.rotation.max-file-size=10M quarkus.log.file.rotation.max-backup-index=10 - -# log in details for frontend -frontend.username=${FRONTEND_USERNAME} -frontend.password=${FRONTEND_PASSWORD} \ No newline at end of file diff --git a/backend/src/test/java/org/acme/security/jpa/JpaSecurityRealmTest.java b/backend/src/test/java/org/acme/security/jpa/JpaSecurityRealmTest.java deleted file mode 100644 index bc0dfd6..0000000 --- a/backend/src/test/java/org/acme/security/jpa/JpaSecurityRealmTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.acme.security.jpa; - -import io.quarkus.test.junit.QuarkusTest; -import jakarta.inject.Inject; -import org.apache.http.HttpStatus; -import org.eclipse.microprofile.config.Config; -import org.junit.jupiter.api.Test; - -import static io.restassured.RestAssured.get; -import static io.restassured.RestAssured.given; -import static org.hamcrest.core.Is.is; - -@QuarkusTest -public class JpaSecurityRealmTest { - @Inject - Config config; - - @Test - void shouldNotAccessLoginWhenAnonymous() { - get("/login") - .then() - .statusCode(HttpStatus.SC_UNAUTHORIZED); - } - - @Test - void shouldNotAccessRoomsWhenAnonymous() { - get("/rooms") - .then() - .statusCode(HttpStatus.SC_UNAUTHORIZED); - } - - @Test - void shouldNotAccessUnitsWhenAnonymous() { - get("/units") - .then() - .statusCode(HttpStatus.SC_UNAUTHORIZED); - } - - @Test - void shouldAccessLoginWhenUserAuthenticated() { - String username = config.getValue("frontend.username", String.class); - String password = config.getValue("frontend.password", String.class); - - given() - .auth().preemptive().basic(username, password) - .when() - .get("/login") - .then() - .statusCode(HttpStatus.SC_OK) - .body(is(username)); - } - - @Test - void shouldAccessRoomsWhenUserAuthenticated() { - String username = config.getValue("frontend.username", String.class); - String password = config.getValue("frontend.password", String.class); - - given() - .auth().preemptive().basic(username, password) - .when() - .get("/rooms") - .then() - .statusCode(HttpStatus.SC_OK); - } - - @Test - void shouldAccessUnitsWhenUserAuthenticated() { - String username = config.getValue("frontend.username", String.class); - String password = config.getValue("frontend.password", String.class); - - given() - .auth().preemptive().basic(username, password) - .when() - .get("/units") - .then() - .statusCode(HttpStatus.SC_OK); - } - -} \ No newline at end of file diff --git a/backend/src/test/java/org/acme/solver/TimetableConstraintProviderTest.java b/backend/src/test/java/org/acme/solver/TimetableConstraintProviderTest.java index 4d29887..979e96e 100644 --- a/backend/src/test/java/org/acme/solver/TimetableConstraintProviderTest.java +++ b/backend/src/test/java/org/acme/solver/TimetableConstraintProviderTest.java @@ -1,16 +1,18 @@ package org.acme.solver; -import ai.timefold.solver.test.api.score.stream.ConstraintVerifier; -import io.quarkus.test.junit.QuarkusTest; -import jakarta.inject.Inject; -import org.acme.domain.*; -import org.junit.jupiter.api.Test; - import java.time.DayOfWeek; import java.time.Duration; import java.time.LocalTime; import java.util.List; +import org.acme.domain.*; + +import jakarta.inject.Inject; +import ai.timefold.solver.test.api.score.stream.ConstraintVerifier; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + @QuarkusTest public class TimetableConstraintProviderTest { private static final Room ROOM1 = new Room("1", "building A", "campus A", 2, true); @@ -35,7 +37,7 @@ public class TimetableConstraintProviderTest { void studentConflict() { Unit firstUnit = new Unit(1, "unit1", "Course A", DAY_OF_WEEK, START_TIME, DURATION, List.of(STUDENT1), true, ROOM1); Unit conflictingUnit = new Unit(2, "unit2", "Course A", DAY_OF_WEEK, START_TIME, DURATION, List.of(STUDENT1), false, ROOM2); - Unit nonConflictingUnit = new Unit(3, "unit3", "Course B", DAY_OF_WEEK, START_TIME, DURATION, List.of(STUDENT2), true, ROOM3); + Unit nonConflictingUnit = new Unit(3, "unit3","Course B", DAY_OF_WEEK, START_TIME, DURATION, List.of(STUDENT2), true, ROOM3); ConflictingUnit conflictingUnitPair = new ConflictingUnit(firstUnit, conflictingUnit, 1); constraintVerifier.verifyThat(TimetableConstraintProvider::studentConflict) diff --git a/frontend/index.html b/frontend/index.html index 07dd708..8076bf4 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,10 +2,10 @@ - + - Timetabling for VIT + Vite + React + TS
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f58f72d..8c492fb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -22,7 +22,7 @@ "react-dom": "^18.3.1", "react-router-dom": "^6.26.1", "read-excel-file": "^5.8.5", - "serve": "^14.2.3", + "serve": "^6.5.8", "vis-timeline": "^7.7.3" }, "devDependencies": { @@ -2185,12 +2185,6 @@ "node": ">=10.0.0" } }, - "node_modules/@zeit/schemas": { - "version": "2.36.0", - "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", - "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==", - "license": "MIT" - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2204,6 +2198,27 @@ "node": ">= 0.6" } }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -2227,6 +2242,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2244,39 +2268,44 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", + "node_modules/align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", + "license": "MIT", + "optional": true, "dependencies": { - "string-width": "^4.1.0" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "license": "BSD-3-Clause OR MIT", + "engines": { + "node": ">=0.4.2" + } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", + "node_modules/ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha512-TdlOggdA/zURfMYa7ABC66j+oqfMew58KpJMbUlH3bcZP1b+cBHIHDDn5uH9INsxrHBPjsqM0tDB4jPTF/vgJA==", + "license": "ISC", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "string-width": "^2.0.0" } }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2315,9 +2344,9 @@ "license": "MIT" }, "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", "license": "MIT" }, "node_modules/argparse": { @@ -2327,6 +2356,44 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/args": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/args/-/args-4.0.0.tgz", + "integrity": "sha512-4b7lVF58nlo7sNtq8s2OueroOY/UHn0Nt/NVjsx9zn28u6yDVb9bQ/uy/5jKtHCbUDil4MlMyDLF5+OHEgnTug==", + "license": "MIT", + "dependencies": { + "camelcase": "5.0.0", + "chalk": "2.3.2", + "leven": "2.1.0", + "mri": "1.1.0" + }, + "engines": { + "node": "> 4.0.0" + } + }, + "node_modules/args/node_modules/chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/args/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -2347,6 +2414,12 @@ "node": ">=12" } }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "license": "MIT" + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -2366,6 +2439,25 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", + "integrity": "sha512-BNzMKPNNIV3+C02TSO9oILCAPS/htf/upL+TRV2gOnPwSQbFKuL249fwVozDNbSq/AeyoRoVeQgJcK4sN77aHg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "license": "MIT" }, "node_modules/bluebird": { @@ -2375,43 +2467,37 @@ "license": "MIT" }, "node_modules/boxen": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", - "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", "license": "MIT", "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.0", - "chalk": "^5.0.1", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "node_modules/boxen/node_modules/camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==", "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4" } }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -2493,15 +2579,12 @@ } }, "node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "license": "MIT", "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/caniuse-lite": { @@ -2525,6 +2608,20 @@ ], "license": "CC-BY-4.0" }, + "node_modules/center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/chai": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", @@ -2556,91 +2653,6 @@ "node": ">=4" } }, - "node_modules/chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" - } - }, - "node_modules/chalk-template/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk-template/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk-template/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk-template/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/chalk-template/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk-template/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/chalk/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2661,32 +2673,47 @@ } }, "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg==", "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/clipboardy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", - "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz", + "integrity": "sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA==", "license": "MIT", "dependencies": { - "arch": "^2.2.0", - "execa": "^5.1.1", - "is-wsl": "^2.2.0" + "arch": "^2.1.0", + "execa": "^0.8.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" + } + }, + "node_modules/cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==", + "license": "ISC", + "optional": true, + "dependencies": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "node_modules/cliui/node_modules/wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==", + "license": "MIT/X11", + "optional": true, + "engines": { + "node": ">=0.4.0" } }, "node_modules/clsx": { @@ -2779,12 +2806,13 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, "license": "MIT" }, - "node_modules/content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -2822,6 +2850,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -2845,6 +2874,15 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/dargs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", + "integrity": "sha512-Mr5OxT76pdJv7BbLq3hF1gSP8zxlCyDA1afj2Iab2MPKmdAKV+aKGC8YJv6cT8ItdFXAf798JJQD7jmbWZcYTQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", @@ -2862,6 +2900,16 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", @@ -2888,6 +2936,53 @@ "dev": true, "license": "MIT" }, + "node_modules/depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha512-Jlk9xvkTDGXwZiIDyoM7+3AsuvJVoyOpRupvEVy9nX3YO3/ieZxhlgh8GpLNZ8AY7HjO6y2YwpMSh1ejhu3uIw==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==", + "license": "MIT" + }, + "node_modules/detect-port": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.2.3.tgz", + "integrity": "sha512-IDbrX6PxqnYy8jV4wSHBaJlErYKTJvW8OQb9F7xivl1iQLqiUYHGa+nZ61Do6+N5uuOn/pReXKNqI9rUn04vug==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/dexie": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/dexie/-/dexie-4.0.8.tgz", @@ -2937,10 +3032,10 @@ "readable-stream": "^2.0.2" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, "node_modules/electron-to-chromium": { @@ -2950,11 +3045,14 @@ "dev": true, "license": "ISC" }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/error-ex": { "version": "1.3.2", @@ -3014,6 +3112,12 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -3289,33 +3393,98 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">=4" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/execa/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/execa/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -3362,21 +3531,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "license": "MIT", - "dependencies": { - "punycode": "^1.3.2" - } - }, - "node_modules/fast-url-parser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "license": "MIT" - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -3412,6 +3566,15 @@ "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", "license": "MIT" }, + "node_modules/filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3469,6 +3632,15 @@ "dev": true, "license": "ISC" }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -3528,15 +3700,12 @@ } }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" } }, "node_modules/glob-parent": { @@ -3599,6 +3768,38 @@ "dev": true, "license": "MIT" }, + "node_modules/handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha512-yrsPfXULrvTP3Aw+zLpett0LUyv2PS/k1jj2UCpYkFElPhMEhspxrCAl4hKGt+vyDjvpxleyYUPF4AMSjCdnhQ==", + "license": "MIT", + "dependencies": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^2.6" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", + "license": "BSD-3-Clause", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -3635,13 +3836,34 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "license": "Apache-2.0", + "node_modules/http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha512-STnYGcKMXL9CGdtpeTFnLmgMSHTTNQJSHxiC4DETHKf934Q160Ht5pljrNeH24S0O9xUN+9vsDJZdZtk5js6Ww==", + "license": "MIT", + "dependencies": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "license": "MIT", "engines": { - "node": ">=10.17.0" + "node": ">=0.10.0" } }, "node_modules/ignore": { @@ -3698,12 +3920,25 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==", + "license": "MIT" + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT", + "optional": true + }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -3719,21 +3954,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3745,12 +3965,12 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/is-glob": { @@ -3786,40 +4006,22 @@ "node": ">=8" } }, - "node_modules/is-port-reachable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", - "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/isarray": { @@ -3960,6 +4162,38 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4012,6 +4246,16 @@ "dev": true, "license": "MIT" }, + "node_modules/longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4054,12 +4298,6 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4070,6 +4308,54 @@ "node": ">= 8" } }, + "node_modules/micro": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/micro/-/micro-9.3.1.tgz", + "integrity": "sha512-83uimpPJqfwkfKvJl2WWontBlV3hmzrIgyJ+L2uhDXKNk7Ll+/ezK3zBz7TljubpKPqjM0JdT2Ker4MTPmhjgA==", + "license": "MIT", + "dependencies": { + "arg": "2.0.0", + "chalk": "2.4.0", + "content-type": "1.0.4", + "is-stream": "1.1.0", + "raw-body": "2.3.2" + }, + "bin": { + "micro": "bin/micro.js" + } + }, + "node_modules/micro-compress": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micro-compress/-/micro-compress-1.0.0.tgz", + "integrity": "sha512-1XM/LoxpfCq9mOgtuT5vwumSGXgCziaT+pZPT1o5Jx9CDc0o6YPma6ACyPuLjchnyi8o80AON7EAw5ZnKQLQyQ==", + "license": "MIT", + "dependencies": { + "compression": "^1.6.2" + } + }, + "node_modules/micro/node_modules/chalk": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/micro/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -4084,6 +4370,15 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "license": "MIT", + "bin": { + "mime": "cli.js" + } + }, "node_modules/mime-db": { "version": "1.53.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", @@ -4094,39 +4389,31 @@ } }, "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "~1.33.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -4136,13 +4423,10 @@ } }, "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==", + "license": "MIT" }, "node_modules/moment": { "version": "2.30.1", @@ -4153,6 +4437,15 @@ "node": "*" } }, + "node_modules/mri": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.0.tgz", + "integrity": "sha512-NbJtWIE2QEVbr9xQHXBY92fxX0Tu8EsS9NBwz7Qn3zoeuvcbP3LzBJw3EUJDpfb9IY8qnZvFSWIepeEFQga28w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4207,16 +4500,34 @@ "dev": true, "license": "MIT" }, + "node_modules/node-version": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/node-version/-/node-version-1.1.3.tgz", + "integrity": "sha512-rEwE51JWn0yN3Wl5BXeGn5d52OGbSXzWiiXRjAQeuyvcGKyvuSILW2rb3G7Xh+nexzLwhTpek6Ehxd6IjvHePg==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", "license": "MIT", "dependencies": { - "path-key": "^3.0.0" + "path-key": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/object-assign": { @@ -4228,6 +4539,18 @@ "node": ">=0.10.0" } }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/on-headers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", @@ -4237,19 +4560,32 @@ "node": ">= 0.8" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/openssl-self-signed-certificate": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz", + "integrity": "sha512-OJpqrdIYir5DznRSChodZqvpOx2fsT6sNA4PD9kYOMkIPgjfNYTWDzgac0drm+ZR0yI5Un7tE8bsmP1nZpx23Q==", + "license": "MIT" + }, + "node_modules/opn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "is-wsl": "^1.1.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" + } + }, + "node_modules/optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", + "license": "MIT/X11", + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" } }, "node_modules/optionator": { @@ -4270,6 +4606,15 @@ "node": ">= 0.8.0" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -4358,6 +4703,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4369,12 +4715,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, - "node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", - "license": "MIT" - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -4420,6 +4760,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", @@ -4492,10 +4841,17 @@ "@egjs/hammerjs": "^2.0.17" } }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "license": "ISC" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4523,14 +4879,29 @@ "license": "MIT" }, "node_modules/range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha512-Ss0DsBxqLxCmQkfG5yazYhtbVVTJqS9jTsZG2lhrNwqzOk2SUC7O/NB/M//CkEBqsrtmlNgJCPccJGuYSFr6Vg==", + "license": "MIT", + "dependencies": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4546,6 +4917,15 @@ "rc": "cli.js" } }, + "node_modules/rc/node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -4698,13 +5078,14 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "license": "MIT", + "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, "node_modules/resolve": { @@ -4740,7 +5121,20 @@ "dev": true, "license": "MIT", "engines": { - "iojs": ">=1.0.0", + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==", + "license": "MIT", + "optional": true, + "dependencies": { + "align-text": "^0.1.1" + }, + "engines": { "node": ">=0.10.0" } }, @@ -4829,101 +5223,168 @@ "semver": "bin/semver.js" } }, - "node_modules/serve": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.3.tgz", - "integrity": "sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==", - "license": "MIT", - "dependencies": { - "@zeit/schemas": "2.36.0", - "ajv": "8.12.0", - "arg": "5.0.2", - "boxen": "7.0.0", - "chalk": "5.0.1", - "chalk-template": "0.4.0", - "clipboardy": "3.0.0", - "compression": "1.7.4", - "is-port-reachable": "4.0.0", - "serve-handler": "6.1.5", - "update-check": "1.5.4" - }, - "bin": { - "serve": "build/main.js" + "node_modules/send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" }, "engines": { - "node": ">= 14" + "node": ">= 0.8.0" } }, - "node_modules/serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.1.2", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" + "ms": "2.0.0" } }, - "node_modules/serve-handler/node_modules/mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "node_modules/send/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/serve-handler/node_modules/mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "node_modules/send/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "license": "MIT", - "dependencies": { - "mime-db": "~1.33.0" - }, "engines": { "node": ">= 0.6" } }, - "node_modules/serve/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/serve": { + "version": "6.5.8", + "resolved": "https://registry.npmjs.org/serve/-/serve-6.5.8.tgz", + "integrity": "sha512-GZYlJz7f6E7Xq6xbg1rTSvQQV9x4v/yYB/sum6egzSBLa/mdk1PViDSX2JvL0Me83sxu3JpEpQELfakDKbGcrw==", + "license": "MIT", + "dependencies": { + "args": "4.0.0", + "basic-auth": "2.0.0", + "bluebird": "3.5.1", + "boxen": "1.3.0", + "chalk": "2.4.1", + "clipboardy": "1.2.3", + "dargs": "5.1.0", + "detect-port": "1.2.3", + "filesize": "3.6.1", + "fs-extra": "6.0.1", + "handlebars": "4.0.11", + "ip": "1.1.5", + "micro": "9.3.1", + "micro-compress": "1.0.0", + "mime-types": "2.1.18", + "node-version": "1.1.3", + "openssl-self-signed-certificate": "1.1.6", + "opn": "5.3.0", + "path-is-inside": "1.0.2", + "path-type": "3.0.0", + "send": "0.16.2", + "update-check": "1.5.1" + }, + "bin": { + "serve": "bin/serve.js" + }, + "engines": { + "node": ">=7.6.0" + } + }, + "node_modules/serve/node_modules/bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "license": "MIT" + }, + "node_modules/serve/node_modules/chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=4" } }, - "node_modules/serve/node_modules/chalk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", - "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "node_modules/serve/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=0.8.0" + } + }, + "node_modules/serve/node_modules/fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/serve/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/serve/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "engines": { + "node": ">=4" } }, - "node_modules/serve/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" + "node_modules/serve/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } }, "node_modules/setimmediate": { "version": "1.0.5", @@ -4931,10 +5392,17 @@ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "license": "MIT" }, + "node_modules/setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha512-9jphSf3UbIgpOX/RKvX02iw/rN2TKdusnsPpGfO/rkcsrd+IRqgHZb4VGnmL0Cynps8Nj2hN45wsi30BzrHDIw==", + "license": "ISC" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -4947,6 +5415,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5001,6 +5470,15 @@ "dev": true, "license": "MIT" }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/std-env": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", @@ -5018,53 +5496,44 @@ } }, "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=4" } }, "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^3.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=4" } }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -5073,13 +5542,13 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/strip-json-comments": { @@ -5125,6 +5594,96 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha512-7dPUZQGy/+m3/wjVz3ZW5dobSoD/02NxJpoXUX0WIyjfVS3l0c+b/+9phIDFA7FHzkYtwtMFgeGZ/Y8jVTeqQQ==", + "license": "MIT", + "dependencies": { + "execa": "^0.7.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/term-size/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/term-size/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/term-size/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/term-size/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/term-size/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5224,18 +5783,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -5274,6 +5821,33 @@ } } }, + "node_modules/uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "source-map": "~0.5.1", + "yargs": "~3.10.0" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + }, + "optionalDependencies": { + "uglify-to-browserify": "~1.0.0" + } + }, + "node_modules/uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==", + "license": "MIT", + "optional": true + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -5283,6 +5857,15 @@ "node": ">= 10.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unzipper": { "version": "0.12.3", "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.3.tgz", @@ -5328,9 +5911,9 @@ } }, "node_modules/update-check": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", - "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.1.tgz", + "integrity": "sha512-M3rjq5KwSrWZrm2GVPIQIF+NXpIn5I9mIV67gGoydptQvzRjLp9ZbM6ctFJeNuaWSm5+mNP7aInELjSiLcIw6A==", "license": "MIT", "dependencies": { "registry-auth-token": "3.3.2", @@ -5341,6 +5924,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -5580,6 +6164,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -5609,18 +6194,24 @@ } }, "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", "license": "MIT", "dependencies": { - "string-width": "^5.0.1" + "string-width": "^2.1.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" + } + }, + "node_modules/window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==", + "optional": true, + "engines": { + "node": ">= 0.8.0" } }, "node_modules/word-wrap": { @@ -5633,60 +6224,13 @@ "node": ">=0.10.0" } }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=0.4.0" } }, "node_modules/xss": { @@ -5722,6 +6266,29 @@ "node": ">= 6" } }, + "node_modules/yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==", + "license": "MIT", + "optional": true, + "dependencies": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "node_modules/yargs/node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index bfc6b7a..ce733a4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,7 +26,7 @@ "react-dom": "^18.3.1", "react-router-dom": "^6.26.1", "read-excel-file": "^5.8.5", - "serve": "^14.2.3", + "serve": "^6.5.8", "vis-timeline": "^7.7.3" }, "devDependencies": { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index aa46501..73cb4cb 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5,6 +5,6 @@ const router = createBrowserRouter(routes); export default function App() { return ( - + ) } \ No newline at end of file diff --git a/frontend/src/assets/cropped-vit-logo.png b/frontend/src/assets/cropped-vit-logo.png deleted file mode 100644 index 7614504..0000000 Binary files a/frontend/src/assets/cropped-vit-logo.png and /dev/null differ diff --git a/frontend/src/components/BackButton.tsx b/frontend/src/components/BackButton.tsx index 3a24823..b30dedf 100644 --- a/frontend/src/components/BackButton.tsx +++ b/frontend/src/components/BackButton.tsx @@ -6,12 +6,11 @@ import { Button } from '@mui/material'; * Displays a button with an arrow icon and text 'Back'. * @returns JSX element representing the back button */ -export default function BackButton({ disabled=false } : {disabled?: boolean}) { +export default function BackButton() { return ( - ); -}; \ No newline at end of file diff --git a/frontend/src/components/NextButton.tsx b/frontend/src/components/NextButton.tsx index 3e3d244..2ab09c0 100644 --- a/frontend/src/components/NextButton.tsx +++ b/frontend/src/components/NextButton.tsx @@ -5,12 +5,11 @@ import { Button } from '@mui/material'; * Component for rendering a button with an arrow icon indicating next action. * @returns JSX element representing the NextButton component */ -export default function NextButton({ disabled=false } : {disabled?: boolean}) { +export default function NextButton() { return ( } else { - return ; + return ; } } \ No newline at end of file diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 777a4cd..fd86d43 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -42,6 +42,15 @@ export default function Sidebar({ marginTop, width }: SidebarProps) { > + + + + + + + + + diff --git a/frontend/src/components/SkipButton.tsx b/frontend/src/components/SkipButton.tsx deleted file mode 100644 index 3e41ffa..0000000 --- a/frontend/src/components/SkipButton.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import Button from "@mui/material/Button"; -import { useNavigate } from "react-router-dom"; - -export default function SkipButton() { - const navigate = useNavigate(); - if (sessionStorage.getItem("campusSolutions") === undefined) { - return ( - - ); - } else { - return ( - - ); - } -} diff --git a/frontend/src/components/UploadButton.tsx b/frontend/src/components/UploadButton.tsx index 98da557..b5a82dc 100644 --- a/frontend/src/components/UploadButton.tsx +++ b/frontend/src/components/UploadButton.tsx @@ -3,8 +3,6 @@ import Button from "@mui/material/Button"; import UploadFileIcon from "@mui/icons-material/UploadFile"; import { getFile, storeFile } from "../scripts/persistence"; import { prefillUnitSpreadsheet } from "../scripts/handleInput"; -import { useState } from "react"; -import { CircularProgress } from "@mui/material"; interface InputFileUploadProps { setFileChosen: (file: File | null) => void; @@ -29,30 +27,25 @@ const VisuallyHiddenInput = styled("input")({ * @param {InputFileUploadProps.setFileChosen} setFileChosen - Callback function to set the chosen file. * @returns Upload button component with file selection and upload functionality. */ -export default function UploadButton({ setFileChosen }: InputFileUploadProps) { - - const [loading, setLoading] = useState(false); +export default function UploadButton ({ setFileChosen }: InputFileUploadProps) { // Handler for file selection const handleFileChange = (event: React.ChangeEvent) => { if (event.target.files && event.target.files.length > 0) { - setLoading(true); storeFile(event.target.files[0]) - .then(() => { - return getFile(); - }) - .then((file) => { - return prefillUnitSpreadsheet(file); - // return getUnitsList(file); - }) - .then((file) => { - setFileChosen(file); - setLoading(false); - }) - .catch((error) => { - alert("Upload failed. Please try again. " + error); - setLoading(false); - }) + .then(() => { + return getFile(); + }) + .then((file) => { + return prefillUnitSpreadsheet(file); + // return getUnitsList(file); + }) + .then((file) => { + setFileChosen(file); + }) + .catch((error) => { + alert("Upload failed. Please try again. " + error); + }) console.log("File selected:", event.target.files[0]); } }; @@ -63,27 +56,10 @@ export default function UploadButton({ setFileChosen }: InputFileUploadProps) { role={undefined} variant="contained" tabIndex={-1} - sx={{ - backgroundColor: '#f05a22', - color: 'white', - '&:hover': { - backgroundColor: '#d1491a', - }, - position: 'relative', - display: 'flex', - alignItems: 'center', - height: 35+"%", - }} - disabled={loading} - startIcon={!loading && } + startIcon={} > - {loading ? ( - - ) : ( - "Upload File" - )} + Upload file ); - } diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index fa2e5a3..4e01bfe 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -2,12 +2,9 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import App from './App.tsx' import './styles/global.css' -import AuthContextProvider from './security/AuthContext.tsx' createRoot(document.getElementById('root')!).render( - - - + ) diff --git a/frontend/src/pages/Enrolment.tsx b/frontend/src/pages/Enrolment.tsx index 1d1cf76..995336e 100644 --- a/frontend/src/pages/Enrolment.tsx +++ b/frontend/src/pages/Enrolment.tsx @@ -4,10 +4,6 @@ import UploadPopUp from "../components/UploadPopUp.tsx"; import Header from "../components/Header.tsx"; import Footer from "../components/Footer.tsx"; import Photo from "../assets/frontpage.jpg"; -import { useEffect } from "react"; -import { REMOTE_API_URL, TimetableSolution } from "../scripts/api.ts"; -import { useAuthContext } from "../security/AuthContext.tsx"; -import SkipButton from "../components/SkipButton.tsx"; /** * Renders the Starter Page component with specific time and tabler styles. @@ -24,26 +20,6 @@ export default function StarterPage() { const tablerStyle = { color: "black", }; - const { authHeader } = useAuthContext(); - useEffect(() => { - fetch(REMOTE_API_URL + "/timetabling/view", { - headers: { Authorization: authHeader }, - }) - .then((response) => { - if (!response.ok) { - throw new Error("Network response was not ok"); - } - return response.json(); - }) - .then((data) => { - const timetableSolutions: TimetableSolution[] = - data as TimetableSolution[]; - sessionStorage.setItem( - "campusSolutions", - JSON.stringify(timetableSolutions) - ); - }); - }, []); return (
@@ -55,7 +31,6 @@ export default function StarterPage() {

A timetabling website for the Victorian Institute of Technology

-Team JetEdge

- logo.exe diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx deleted file mode 100644 index 195e094..0000000 --- a/frontend/src/pages/LoginPage.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { AuthHeader, useAuthContext } from '../security/AuthContext'; -import '../styles/login.css'; -import VIT_Logo from '../assets/logo.png'; -import { REMOTE_API_URL } from '../scripts/api'; -import LoadingButton from '../components/LoadingButton'; - -export default function LoginPage() { - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); - const [loading, setLoading] = useState(false); - const navigate = useNavigate(); - - const { setAuthHeader } = useAuthContext(); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - setLoading(true); - - const encodedHeader: AuthHeader = `Basic ${btoa(`${username}:${password}`)}`; - - try { - // Send a request to the backend to validate credentials - const response = await fetch(REMOTE_API_URL + "/login", { - method: 'GET', - headers: { - 'Authorization': encodedHeader, - }, - }); - - if (response.status != 401) { - setAuthHeader(encodedHeader); - navigate("/enrolment"); - } - else { - alert("Unauthorised"); - } - } - catch (error) { - alert(error); - } - finally { - setLoading(false); - } - - } - - return ( -
-
- {/* Logo at the top */} - Logo - -

Login

- -
- setUsername(e.target.value)} - className="login-input" - required - /> -
- -
- setPassword(e.target.value)} - className="login-input" - required - /> -
- - {}} - text="Login" - type='submit' - sx={{ - width: '100%', - height: '40px', - marginTop: '2px', - }} - /> - -
- ); -}; \ No newline at end of file diff --git a/frontend/src/pages/SemesterInfo.tsx b/frontend/src/pages/SemesterInfo.tsx index 816f87c..4a00ccc 100644 --- a/frontend/src/pages/SemesterInfo.tsx +++ b/frontend/src/pages/SemesterInfo.tsx @@ -25,7 +25,7 @@ export default function SemesterInfo() {
- +
diff --git a/frontend/src/pages/SendData.tsx b/frontend/src/pages/SendData.tsx index e96a357..ec90966 100644 --- a/frontend/src/pages/SendData.tsx +++ b/frontend/src/pages/SendData.tsx @@ -7,8 +7,6 @@ import { DB_ROOMS, DB_UNITS, getSpreadsheetData } from "../scripts/persistence"; import { getTimetableProblems } from "../scripts/handleInput"; import { useState } from "react"; import { fetchTimetableSolution } from "../scripts/api"; -import { useAuthContext } from '../security/AuthContext'; -import LoadingButton from "../components/LoadingButton"; /** * Page for containing UI elements that allow user to send input data to backend. @@ -20,14 +18,10 @@ import LoadingButton from "../components/LoadingButton"; */ export default function SendData() { - const [loading, setLoading] = useState(false); - const { authHeader } = useAuthContext(); + const [isGenerated, setIsGenerated] = useState(""); function generateTimetable() { - setLoading(true); - setTimeout(() => { - setLoading(false); - }, 120000); + setIsGenerated(""); Promise.all([getSpreadsheetData(DB_ROOMS), getSpreadsheetData(DB_UNITS)]) .then((responses) => { const [roomData, unitData] = [...responses]; @@ -40,37 +34,28 @@ export default function SendData() { return getTimetableProblems(roomData, unitData); }) .then((problems) => { - return Promise.all(problems.map(p => fetchTimetableSolution(p, authHeader))); + return Promise.all(problems.map(p => fetchTimetableSolution(p))); }) .then((solutions) => { console.log(solutions); - // setLoading(false); + setIsGenerated(JSON.stringify(solutions, null, 2)); }) .catch((error) => { alert(error); - // setLoading(false); }) } return ( <>
-
- +
+
{isGenerated.toString()}
+
- {loading ? ( - <> - - - - ) : ( - <> - - - - )} + +
diff --git a/frontend/src/pages/TimetableMod.tsx b/frontend/src/pages/TimetableMod.tsx index 0c321bf..bcb7fa6 100644 --- a/frontend/src/pages/TimetableMod.tsx +++ b/frontend/src/pages/TimetableMod.tsx @@ -5,8 +5,7 @@ import Footer from "../components/Footer"; import BackButton from "../components/BackButton"; import { Outlet } from "react-router-dom"; import ModSidebar from "../components/ModSiderbar"; -import { REMOTE_API_URL, TimetableSolution } from "../scripts/api"; -import { useAuthContext } from "../security/AuthContext"; +import { TimetableSolution } from "../scripts/api"; /** * Renders the TimetableMod component to display and modify the generated @@ -17,10 +16,9 @@ import { useAuthContext } from "../security/AuthContext"; */ export default function TimetableMod() { const [loading, setLoading] = useState(true); - const { authHeader } = useAuthContext(); useEffect(() => { - fetch(REMOTE_API_URL + "/timetabling/view", { headers: { 'Authorization': authHeader } }) + fetch("http://localhost:8080/timetabling/view") .then((response) => { if (!response.ok) { throw new Error("Network response was not ok"); @@ -56,8 +54,10 @@ export default function TimetableMod() {
- - + + + +
diff --git a/frontend/src/pages/spreadsheets/Building.tsx b/frontend/src/pages/spreadsheets/Building.tsx new file mode 100644 index 0000000..be3ccc9 --- /dev/null +++ b/frontend/src/pages/spreadsheets/Building.tsx @@ -0,0 +1,19 @@ +import Spreadsheet from '../../components/Spreadsheet.tsx' +import { DB_BUILDINGS } from '../../scripts/persistence.ts'; + +/** + * + * @returns Spreadsheet input page for buildings information. + */ +export default function Building() { + + return ( + <> +

Building

+ + + ); +}; \ No newline at end of file diff --git a/frontend/src/routes.tsx b/frontend/src/routes.tsx index fcdc0c5..48d05c2 100644 --- a/frontend/src/routes.tsx +++ b/frontend/src/routes.tsx @@ -1,14 +1,12 @@ import SemesterInfo from './pages/SemesterInfo.tsx' import TimetableMod from './pages/TimetableMod.tsx' +import Building from './pages/spreadsheets/Building.tsx' import Room from './pages/spreadsheets/Room.tsx' import Unit from './pages/spreadsheets/Unit.tsx' import Download from './pages/Download.tsx' import Enrolment from './pages/Enrolment.tsx' import SendData from './pages/SendData.tsx' import GanttChart from './components/GanttChart.tsx' -import LoginPage from './pages/LoginPage.tsx' -import { Navigate } from 'react-router-dom' -import PrivateRoute from './security/PrivateRoute.tsx' /** * Defines the routes configuration for the application. * Each route specifies a path and the corresponding component to render. @@ -18,38 +16,31 @@ import PrivateRoute from './security/PrivateRoute.tsx' const routes = [ { path: "/", - element: , - }, - { - path: "/login", - element: , - }, - { - path: "enrolment", - element: } />, + element: , }, { path: "seminfo", - element: } />, + element: , children: [ + { path: "building", element: }, { path: "room", element: }, { path: "unit", element: }, ], }, { path: "senddata", - element: } />, + element: , }, { path: "timetablemod/*", - element: } />, + element: , children: [ {path: ":location", element: } ], }, { path: "download", - element: } />, + element: , }, ]; diff --git a/frontend/src/scripts/api.ts b/frontend/src/scripts/api.ts index ceb1357..c49eff6 100644 --- a/frontend/src/scripts/api.ts +++ b/frontend/src/scripts/api.ts @@ -1,8 +1,5 @@ -import { AuthHeader } from "../security/AuthContext"; - /* Timetable solver backend endpoint URL */ -export const REMOTE_API_URL = "https://jetedge-backend-e1eeff4b0c04.herokuapp.com"; -export const LOCAL_API_URL = "http://localhost:8080"; +const API_URL = "http://localhost:8080/timetabling"; /* =========================================== Defining types =========================================== */ @@ -62,24 +59,19 @@ export type Time = string; * @param problem A TimetableProblem is a list of units with no allocated time and room. * @returns A TimetableSolution with all units allocated a time and a room. */ -export async function fetchTimetableSolution(problem: TimetableProblem, authHeader: AuthHeader, url?: string): Promise { +export async function fetchTimetableSolution(problem: TimetableProblem): Promise { try { - let api_url = REMOTE_API_URL; - if (url !== undefined) { - api_url = url; - } - const response = await fetch(api_url+"/timetabling", { + const response = await fetch(API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': authHeader, }, body: JSON.stringify(problem) }); if (!response.ok) { if (response.status === 500) { - alert(response.statusText + " " + response.status + ": server was not able to solve the problem."); + alert(response.statusText + " " + response.status + ": server was not able to solve the problem. Please check for missing input (i.e. make sure there are at least 1 available room and no rooms with duplicate ID)."); } throw new Error(`HTTP error! Status: ${response.status} ${response.statusText}`); } diff --git a/frontend/src/scripts/handleInput.ts b/frontend/src/scripts/handleInput.ts index 81ada5f..51bf38a 100644 --- a/frontend/src/scripts/handleInput.ts +++ b/frontend/src/scripts/handleInput.ts @@ -12,6 +12,7 @@ import { DB_UNITS, storeSpreadsheetData } from './persistence'; function isExcelFile(file: File) { const fileExtension = file.name.split('.').pop(); if (fileExtension === undefined || !['xlsx', 'xls'].includes(fileExtension)) { + alert("Wrong file type, file type must be .xlsx or .xls"); return false; } return true; @@ -32,6 +33,7 @@ function validateEnrolmentHeader(inputHeader: Row) { return true; } else { + alert("Enrolment data header row is invalid"); return false; } } @@ -132,9 +134,7 @@ export async function prefillUnitSpreadsheet(enrolmentExcel: File) { const units = unitsMaps.map(m => { const unitsData = Array.from(m.values()); - const transformed = unitsData - .filter((ud) => ud.enrolment.length > 0) - .map(ud => { return { ...ud, enrolment: JSON.stringify(ud.enrolment) } }); + const transformed = unitsData.map(ud => { return { ...ud, enrolment: JSON.stringify(ud.enrolment) } }); return transformed; }).flat(); diff --git a/frontend/src/security/AuthContext.tsx b/frontend/src/security/AuthContext.tsx deleted file mode 100644 index 89286ca..0000000 --- a/frontend/src/security/AuthContext.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { createContext, useState, ReactNode, useContext } from 'react'; - -export type AuthHeader = `Basic ${string}` | ''; - -type AuthContext = { - authHeader: AuthHeader; - setAuthHeader: React.Dispatch>; -}; - -const AuthContext = createContext(undefined); - -export default function AuthContextProvider({ children }: { children: ReactNode }) { - const [authHeader, setAuthHeader] = useState(''); - - return ( - - {children} - - ); -}; - -export const useAuthContext = () => { - const context = useContext(AuthContext); - if (!context) { - throw new Error('useAuthContext must be used within an AuthContextProvider'); - } - return context; -}; \ No newline at end of file diff --git a/frontend/src/security/PrivateRoute.tsx b/frontend/src/security/PrivateRoute.tsx deleted file mode 100644 index 14464ef..0000000 --- a/frontend/src/security/PrivateRoute.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useAuthContext } from './AuthContext'; -import { Navigate } from 'react-router-dom'; - -export default function PrivateRoute({ element }: { element: JSX.Element }) { - const { authHeader } = useAuthContext(); - - // If no credentials are set, redirect to the login page - if (authHeader === '') { - return ; - } - - return element; -}; \ No newline at end of file diff --git a/frontend/src/styles/login.css b/frontend/src/styles/login.css deleted file mode 100644 index 721ad43..0000000 --- a/frontend/src/styles/login.css +++ /dev/null @@ -1,79 +0,0 @@ -/* Container */ -.login-container { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - background-color: #f9f9f9; -} - -/* Form */ -.login-form { - background-color: #fff; - padding: 2rem; - border-radius: 10px; - box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); - width: 100%; - max-width: 400px; - display: flex; - flex-direction: column; - align-items: center; -} - -/* Logo */ -.login-logo { - width: 30%; /* Adjust the size of the logo */ - height: auto; - margin-bottom: 0.5rem; /* Space between logo and title */ -} - -/* Title */ -.login-title { - color: #333; - margin-bottom: 1.5rem; - font-size: 24px; - text-align: center; -} - -/* Input Wrapper */ -.input-group { - width: 100%; - margin-bottom: 1rem; -} - -/* Input */ -.login-input { - box-sizing: border-box; - width: 100%; - padding: 12px; - border-radius: 5px; - border: 1px solid #ccc; - font-size: 16px; - transition: border-color 0.3s ease; -} - -.login-input:focus { - outline: none; - border-color: #f05a22; -} - -/* Button */ -.login-button { - background-color: #f05a22; - color: white; - border: none; - padding: 12px; - border-radius: 5px; - font-size: 16px; - cursor: pointer; - width: 100%; - transition: background-color 0.3s ease; -} - -.login-button:hover { - background-color: #e0481f; -} - -.login-button:active { - background-color: #cc3d1b; -} diff --git a/frontend/src/tests/api.test.ts b/frontend/src/tests/api.test.ts index 0f26572..fe9d6fe 100644 --- a/frontend/src/tests/api.test.ts +++ b/frontend/src/tests/api.test.ts @@ -1,29 +1,26 @@ import { describe, it, expect } from 'vitest'; -import { fetchTimetableSolution, LOCAL_API_URL, TimetableProblem } from '../scripts/api'; +import { fetchTimetableSolution, TimetableProblem } from '../scripts/api'; import moment from 'moment'; -import { AuthHeader } from '../security/AuthContext'; /** * Test fetchTimetableSolution API method. * Check if connection to backend is working. * Check that output matches expected output. */ -describe('fetchTimetableSolution', { timeout: 200000 }, () => { +describe('fetchTimetableSolution', { timeout: 60000 }, () => { /** * Validate end-to-end scheduling and data consistency of 1 API method call. */ it('return TimetableSolution', async () => { const problem: TimetableProblem = { - campusName: "Geelong", - units: [{ campus: "Geelong", course: "B", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], + campusName: "A", + units: [{ campus: "A", course: "B", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], daysOfWeek: ["MONDAY"], startTimes: ["11:00:00"], - rooms: [{ campus: "Geelong", buildingId: "01", roomCode: "Room A", capacity: 10, lab: true }] + rooms: [{ campus: "A", buildingId: "01", roomCode: "Room A", capacity: 10, lab: true }] }; - - const authHeader: AuthHeader = `Basic ${btoa(`${import.meta.env.VITE_FRONTEND_USERNAME}:${import.meta.env.VITE_FRONTEND_PASSWORD}`)}`; - - const solution = await fetchTimetableSolution(problem, authHeader, LOCAL_API_URL); + + const solution = await fetchTimetableSolution(problem); expect(solution).not.toBeNull(); expect(solution?.units[0].dayOfWeek).toEqual(problem.daysOfWeek[0]); expect(solution?.units[0].startTime).toEqual(problem.startTimes[0]); @@ -38,24 +35,15 @@ describe('fetchTimetableSolution', { timeout: 200000 }, () => { * Validate that backend server can handle multiple solve requests concurrently. */ it ('can be called multiple times', async () => { - const problem0: TimetableProblem = { - campusName: "Adelaide", - units: [{ campus: "Adelaide", course: "C", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], - daysOfWeek: ["MONDAY"], - startTimes: ["11:00:00"], - rooms: [{ campus: "Adelaide", buildingId: "02", roomCode: "Room A", capacity: 10, lab: true }] - }; - - const problem1: TimetableProblem = { - campusName: "Melbourne", - units: [{ campus: "Melbourne", course: "C", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], + const problem: TimetableProblem = { + campusName: "B", + units: [{ campus: "B", course: "C", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], daysOfWeek: ["MONDAY"], startTimes: ["11:00:00"], - rooms: [{ campus: "Melbourne", buildingId: "02", roomCode: "Room A", capacity: 10, lab: true }] + rooms: [{ campus: "B", buildingId: "02", roomCode: "Room A", capacity: 10, lab: true }] }; - const authHeader: AuthHeader = `Basic ${btoa(`${import.meta.env.VITE_FRONTEND_USERNAME}:${import.meta.env.VITE_FRONTEND_PASSWORD}`)}`; - const solutions = await Promise.all([fetchTimetableSolution(problem0, authHeader, LOCAL_API_URL), fetchTimetableSolution(problem1, authHeader, LOCAL_API_URL)]); + const solutions = await Promise.all([fetchTimetableSolution(problem), fetchTimetableSolution(problem), fetchTimetableSolution(problem)]); for (let i = 0; i < solutions.length; i++) { expect(solutions[i]).not.toBeNull();