From 812bc03e2c9dea657391a1bf4ecfc36cebcfe5a4 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Mon, 28 Mar 2022 00:49:35 +0800 Subject: [PATCH 01/21] Update Model Updated Model and Model Manager class to allow modification of data in memory --- src/main/java/seedu/address/model/Model.java | 3 +++ src/main/java/seedu/address/model/ModelManager.java | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 78c884e225b..1c116cc8b16 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -4,6 +4,7 @@ import java.util.function.Predicate; import javafx.collections.ObservableList; +import javafx.collections.transformation.FilteredList; import seedu.address.commons.core.GuiSettings; import seedu.address.model.application.Application; @@ -85,4 +86,6 @@ public interface Model { * @throws NullPointerException if {@code predicate} is null. */ void updateFilteredApplicationList(Predicate predicate); + + void setFilteredApplicationList(FilteredList filteredApplications); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 75c59a0d912..9ebaaeb6ad6 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -129,6 +129,13 @@ public void updateFilteredApplicationList(Predicate predicate) { filteredApplications.setPredicate(predicate); } + @Override + public void setFilteredApplicationList(FilteredList filteredApplications) { + requireNonNull(filteredApplications); + //this.filteredApplications.clear(); + //this.filteredApplications.addAll(filteredApplications); + } + @Override public boolean equals(Object obj) { // short circuit if same object From 8d5382dd332b97d3ce9948e1ed1b71facd562bd9 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Mon, 28 Mar 2022 00:51:26 +0800 Subject: [PATCH 02/21] Add Comparators Added 3 comparators (name, interview slot, priority) to allow sorting of applications via the 3 fields --- .../logic/sort/InterviewSlotComparator.java | 15 +++++++ .../address/logic/sort/NameComparator.java | 15 +++++++ .../logic/sort/PriorityComparator.java | 39 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java create mode 100644 src/main/java/seedu/address/logic/sort/NameComparator.java create mode 100644 src/main/java/seedu/address/logic/sort/PriorityComparator.java diff --git a/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java b/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java new file mode 100644 index 00000000000..bab0e18d5dd --- /dev/null +++ b/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java @@ -0,0 +1,15 @@ +package seedu.address.logic.sort; + +import java.util.Comparator; + +import seedu.address.model.application.Application; + +public class InterviewSlotComparator implements Comparator { + + public static final String COMMAND_WORD = "interview"; + + @Override + public int compare(Application o1, Application o2) { + return o1.getInterviewSlot().getValue().compareTo(o2.getInterviewSlot().getValue()); + } +} diff --git a/src/main/java/seedu/address/logic/sort/NameComparator.java b/src/main/java/seedu/address/logic/sort/NameComparator.java new file mode 100644 index 00000000000..02950ac3aac --- /dev/null +++ b/src/main/java/seedu/address/logic/sort/NameComparator.java @@ -0,0 +1,15 @@ +package seedu.address.logic.sort; + +import java.util.Comparator; + +import seedu.address.model.application.Application; + +public class NameComparator implements Comparator { + + public static final String COMMAND_WORD = "name"; + + @Override + public int compare(Application o1, Application o2) { + return o1.getName().toString().compareTo(o2.getName().toString()); + } +} diff --git a/src/main/java/seedu/address/logic/sort/PriorityComparator.java b/src/main/java/seedu/address/logic/sort/PriorityComparator.java new file mode 100644 index 00000000000..4b34cb2cb5e --- /dev/null +++ b/src/main/java/seedu/address/logic/sort/PriorityComparator.java @@ -0,0 +1,39 @@ +package seedu.address.logic.sort; + +import java.util.Comparator; +import java.util.Optional; + +import seedu.address.model.application.Application; +import seedu.address.model.tag.PriorityTag; +import seedu.address.model.tag.PriorityTagType; + +public class PriorityComparator implements Comparator { + + public static final String COMMAND_WORD = "priority"; + + @Override + public int compare(Application o1, Application o2) { + Optional p1 = o1.getPriorityTag(); + Optional p2 = o2.getPriorityTag(); + + if (p1.isPresent() && p2.isEmpty()) { + return 1; + } else if (p1.isEmpty() && p2.isPresent()) { + return -1; + } else if (p1.isEmpty()) { + return o1.getName().toString().compareTo(o2.getName().toString()); + } else { + if (p1.get().toString().equals(p2.get().toString())) { + return 0; + } else if (p1.get().toString().equals(PriorityTagType.HIGH.toString())) { + return 1; + } else if (p2.get().toString().equals(PriorityTagType.HIGH.toString())) { + return -1; + } else if (p2.get().toString().equals(PriorityTagType.LOW.toString())) { + return 1; + } else { + return -1; + } + } + } +} From 9a3f3159800d8bb7f9f6d57e006f688b9a273f58 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Mon, 28 Mar 2022 00:53:08 +0800 Subject: [PATCH 03/21] Add command parser for list command - Added command parser for list to handle different sorting arguments - Updated InternApplyParser to handle arguments for list command --- .../logic/parser/InternApplyParser.java | 2 +- .../logic/parser/ListCommandParser.java | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/address/logic/parser/ListCommandParser.java diff --git a/src/main/java/seedu/address/logic/parser/InternApplyParser.java b/src/main/java/seedu/address/logic/parser/InternApplyParser.java index fb93fa3dbf9..2ee2e666768 100644 --- a/src/main/java/seedu/address/logic/parser/InternApplyParser.java +++ b/src/main/java/seedu/address/logic/parser/InternApplyParser.java @@ -60,7 +60,7 @@ public Command parseCommand(String userInput) throws ParseException { return new FindCommandParser().parse(arguments); case ListCommand.COMMAND_WORD: - return new ListCommand(); + return new ListCommandParser().parse(arguments); case ExitCommand.COMMAND_WORD: return new ExitCommand(); diff --git a/src/main/java/seedu/address/logic/parser/ListCommandParser.java b/src/main/java/seedu/address/logic/parser/ListCommandParser.java new file mode 100644 index 00000000000..d031a7864a2 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/ListCommandParser.java @@ -0,0 +1,60 @@ +package seedu.address.logic.parser; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.commands.ListCommand.COMMAND_ORDER_WORD_ASCENDING; +import static seedu.address.logic.commands.ListCommand.COMMAND_ORDER_WORD_DESCENDING; + +import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.logic.sort.InterviewSlotComparator; +import seedu.address.logic.sort.NameComparator; +import seedu.address.logic.sort.PriorityComparator; + +/** + * Parses input arguments and creates a new ListCommand object + */ +public class ListCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the ListCommand + * and returns a ListCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public ListCommand parse(String args) throws ParseException { + String trimmedArgs = args.trim(); + + if (trimmedArgs.isEmpty()) /* Handles default list */ { + return new ListCommand(); + } + + String[] sortingArgs = trimmedArgs.split("\\s+"); + + if (sortingArgs.length == 1) { + String keyword = sortingArgs[0]; + if (keyword.equals(COMMAND_ORDER_WORD_DESCENDING)) { + return new ListCommand(null, COMMAND_ORDER_WORD_DESCENDING); + } else if (keyword.equals(COMMAND_ORDER_WORD_ASCENDING)) { + return new ListCommand(); + } + } else { + String sortingField = sortingArgs[0]; + String orderBy = sortingArgs[1]; + + if (validateOrderBy(orderBy)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE)); + } else if (sortingField.equals(NameComparator.COMMAND_WORD)) { + return new ListCommand(new NameComparator(), orderBy); + } else if (sortingField.equals(InterviewSlotComparator.COMMAND_WORD)) { + return new ListCommand(new InterviewSlotComparator(), orderBy); + } else if (sortingField.equals(PriorityComparator.COMMAND_WORD)) { + return new ListCommand(new PriorityComparator(), orderBy); + } + } + + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE)); + } + + private boolean validateOrderBy(String s) { + return !s.equals(COMMAND_ORDER_WORD_DESCENDING) && !s.equals(COMMAND_ORDER_WORD_ASCENDING); + } +} From b681e970b95aa47d03b68bb18ef50ea6395892a5 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Mon, 28 Mar 2022 00:54:46 +0800 Subject: [PATCH 04/21] Update list command - Added sortingComparator and orderBy field - Updated execute to sort model --- .../address/logic/commands/ListCommand.java | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 4e5337d5938..a9b32a7d141 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -3,7 +3,16 @@ import static java.util.Objects.requireNonNull; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_APPLICATIONS; +import javafx.collections.transformation.FilteredList; +import seedu.address.logic.sort.InterviewSlotComparator; +import seedu.address.logic.sort.NameComparator; +import seedu.address.logic.sort.PriorityComparator; import seedu.address.model.Model; +import seedu.address.model.application.Application; +import seedu.address.model.application.NameContainsKeywordsPredicate; + +import java.util.Comparator; +import java.util.Optional; /** * Lists all applications in InternApply to the user. @@ -12,13 +21,53 @@ public class ListCommand extends Command { public static final String COMMAND_WORD = "list"; - public static final String MESSAGE_SUCCESS = "Listed all applications"; + public static final String COMMAND_ORDER_WORD_ASCENDING = "ASC"; + + public static final String COMMAND_ORDER_WORD_DESCENDING = "DESC"; + + public static final String MESSAGE_SUCCESS = "Listed filtered applications"; + // TODO: Update it to variable as per edit + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Show a filtered list of all applications with the " + + "selected parameter.\n" + + "Parameters: [FIELD " + + NameComparator.COMMAND_WORD + "|" + + InterviewSlotComparator.COMMAND_WORD + "|" + + PriorityComparator.COMMAND_WORD + " " + + "[ORDER " + COMMAND_ORDER_WORD_ASCENDING + "|" + COMMAND_ORDER_WORD_DESCENDING + "] \n" + + "Example: " + COMMAND_WORD + " INTERVIEW " + COMMAND_ORDER_WORD_DESCENDING + "\n" + + "Note: For default listing use " + COMMAND_WORD + " [ORDER] without the sorting field."; + + private final Optional> sortingComparator; + private final String orderBy; + public ListCommand() { + sortingComparator = Optional.empty(); + orderBy = COMMAND_ORDER_WORD_ASCENDING; + } + + public ListCommand(Comparator sortingComparator, String orderBy) { + this.sortingComparator = Optional.ofNullable(sortingComparator); + this.orderBy = orderBy; + } @Override public CommandResult execute(Model model) { requireNonNull(model); model.updateFilteredApplicationList(PREDICATE_SHOW_ALL_APPLICATIONS); + + FilteredList filteredApplications = new FilteredList<>(model + .getInternApplyMemory().getApplicationList()); + + if (sortingComparator.isEmpty()) { + model.setFilteredApplicationList(filteredApplications); + } else { +// filteredApplications.sort(sortingComparator.get()); +// model.setFilteredApplicationList(filteredApplications); + System.out.println("ok"); + model.getFilteredApplicationList().sort(sortingComparator.get()); + } return new CommandResult(MESSAGE_SUCCESS); } } From 12097f09c3e2b78b45d0509398b4c640b5619cb3 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Mon, 28 Mar 2022 00:55:29 +0800 Subject: [PATCH 05/21] Add getter for InterviewSlot and PriorityTag fields --- .../seedu/address/model/application/Application.java | 11 +++++++++++ .../address/model/application/InterviewSlot.java | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/seedu/address/model/application/Application.java b/src/main/java/seedu/address/model/application/Application.java index 429104e1799..4c4b0ef464f 100644 --- a/src/main/java/seedu/address/model/application/Application.java +++ b/src/main/java/seedu/address/model/application/Application.java @@ -5,8 +5,10 @@ import java.util.Collections; import java.util.HashSet; import java.util.Objects; +import java.util.Optional; import java.util.Set; +import seedu.address.model.tag.PriorityTag; import seedu.address.model.tag.Tag; /** @@ -79,6 +81,15 @@ public Details getDetails() { return details; } + public Optional getPriorityTag() { + for (Tag tag: tags) { + if (tag instanceof PriorityTag) { + return Optional.of((PriorityTag) tag); + } + } + return Optional.empty(); + } + /** * Returns an immutable tag set, which throws {@code UnsupportedOperationException} * if modification is attempted. diff --git a/src/main/java/seedu/address/model/application/InterviewSlot.java b/src/main/java/seedu/address/model/application/InterviewSlot.java index 9f6af44981c..a7c7a3fdd57 100644 --- a/src/main/java/seedu/address/model/application/InterviewSlot.java +++ b/src/main/java/seedu/address/model/application/InterviewSlot.java @@ -61,6 +61,10 @@ public static boolean isNotSet(String test) { .ofPattern(InterviewSlot.FORMAT_DATETIME_INPUT))); } + public LocalDateTime getValue() { + return this.value; + } + /** * Returns the value of interview slot in the input String format as per FORMAT_DATETIME_INPUT. */ From 238da35354148e84a114694a85a94b82504764f2 Mon Sep 17 00:00:00 2001 From: lchokhoe Date: Mon, 28 Mar 2022 09:13:28 +0800 Subject: [PATCH 06/21] Update SampleDataUtil#getSampleApplication() method. Currently, the method is being used to create Sample Data that will be used to populate InternApply's application list. This method is only called if an existing internapplymemory.json file is not detected in the data folder. The Sample Data is a hard coded set of applications. This means that the Interview Slots created are generally going to be irrelevant at some point. Let's implement a way to generate Interview Slots that are more useful. To do this, we want to check for the LocalDateTime.now() of the local machine and use that to generate our Interview Slots. This ensures that no matter which user is using InternApply or when they are using InternApply, the Sample Data generated (if needed) will be relevant relative to the actual current local date time of his/her machine. --- .../address/model/util/SampleDataUtil.java | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 25c55be2e35..7a13e11cc94 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -1,5 +1,7 @@ package seedu.address.model.util; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; @@ -21,25 +23,49 @@ */ public class SampleDataUtil { public static Application[] getSampleApplications() { + LocalDateTime today = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm"); return new Application[] { - - new Application(new Name("Shopee"), new JobTitle("Software Engineer Intern"), new Phone("87438807"), - new Email("hr@shopee.sg"), new Address("5 Science Park Dr, #06-40"), new InterviewSlot(), - new Details(), getTagSet("singapore", "HIGH", "INTERVIEWED")), - new Application(new Name("Grab Holdings Singapore"), new JobTitle("AI Engineer"), new Phone("99272758"), - new Email("hr@grab.sg"), new Address("3 Media Cl, #07-18"), new InterviewSlot(), - new Details(), getTagSet("colleagues", "friends", "MEDIUM", "APPLIED")), - new Application(new Name("Microsoft"), new JobTitle("Software Engineer Intern"), new Phone("93210283"), - new Email("hr@microsoft.com"), new Address("182 Cecil St, #13-01"), new InterviewSlot(), - new Details(), getTagSet("overseas", "LOW", "NOT_APPLIED")), - new Application(new Name("Aftershock PC"), new JobTitle("Data Scientist"), new Phone("63458727"), - new Email("corpsales@sg.aftershockpc.com"), new Address("994, Bendemeer Rd, #05-07"), - new InterviewSlot("17-04-2022 12:00"), - new Details(), getTagSet("passion", "HIGH", "APPLIED")), - new Application(new Name("Google Asia Pacific"), new JobTitle("ML Engineer"), new Phone("91031282"), - new Email("hr@google.com"), new Address("70 Pasir Panjang Rd, #16-43"), - new InterviewSlot("28-03-2022 13:00"), - new Details(), getTagSet("family", "LOW", "REJECTED")), + new Application(new Name("Shopee"), + new JobTitle("Software Engineer Intern"), + new Phone("87438807"), + new Email("hr@shopee.sg"), + new Address("5 Science Park Dr, #06-40"), + new InterviewSlot(), + new Details(), + getTagSet("singapore", "HIGH", "INTERVIEWED")), + new Application(new Name("Grab Holdings Singapore"), + new JobTitle("AI Engineer"), + new Phone("99272758"), + new Email("hr@grab.sg"), + new Address("3 Media Cl, #07-18"), + new InterviewSlot(today.minusDays(1).format(formatter)), + new Details(), + getTagSet("colleagues", "friends", "MEDIUM", "APPLIED")), + new Application(new Name("Microsoft"), + new JobTitle("Software Engineer Intern"), + new Phone("93210283"), + new Email("hr@microsoft.com"), + new Address("182 Cecil St, #13-01"), + new InterviewSlot(today.plusDays(1).format(formatter)), + new Details(), + getTagSet("overseas", "LOW", "NOT_APPLIED")), + new Application(new Name("Aftershock PC"), + new JobTitle("Data Scientist"), + new Phone("63458727"), + new Email("corpsales@sg.aftershockpc.com"), + new Address("994, Bendemeer Rd, #05-07"), + new InterviewSlot(today.plusDays(7).format(formatter)), + new Details(), + getTagSet("passion", "HIGH", "APPLIED")), + new Application(new Name("Google Asia Pacific"), + new JobTitle("ML Engineer"), + new Phone("91031282"), + new Email("hr@google.com"), + new Address("70 Pasir Panjang Rd, #16-43"), + new InterviewSlot(today.plusDays(8).format(formatter)), + new Details(), + getTagSet("family", "LOW", "REJECTED")), }; } From 0c6be878e54bc56c946b297768a7292788619bcc Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Tue, 29 Mar 2022 15:45:59 +0800 Subject: [PATCH 07/21] Update Priority Comparator Fixed priority comparator comparing wrong values. --- .../address/logic/sort/PriorityComparator.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/address/logic/sort/PriorityComparator.java b/src/main/java/seedu/address/logic/sort/PriorityComparator.java index 4b34cb2cb5e..e6c40f16f2a 100644 --- a/src/main/java/seedu/address/logic/sort/PriorityComparator.java +++ b/src/main/java/seedu/address/logic/sort/PriorityComparator.java @@ -4,17 +4,20 @@ import java.util.Optional; import seedu.address.model.application.Application; -import seedu.address.model.tag.PriorityTag; import seedu.address.model.tag.PriorityTagType; +import seedu.address.model.tag.Tag; public class PriorityComparator implements Comparator { public static final String COMMAND_WORD = "priority"; + private static final String PRIORITY_HIGH = "[" + PriorityTagType.HIGH + "]"; + private static final String PRIORITY_LOW = "[" + PriorityTagType.LOW + "]"; + @Override public int compare(Application o1, Application o2) { - Optional p1 = o1.getPriorityTag(); - Optional p2 = o2.getPriorityTag(); + Optional p1 = o1.getPriorityTag(); + Optional p2 = o2.getPriorityTag(); if (p1.isPresent() && p2.isEmpty()) { return 1; @@ -24,12 +27,12 @@ public int compare(Application o1, Application o2) { return o1.getName().toString().compareTo(o2.getName().toString()); } else { if (p1.get().toString().equals(p2.get().toString())) { - return 0; - } else if (p1.get().toString().equals(PriorityTagType.HIGH.toString())) { + return o1.getName().toString().compareTo(o2.getName().toString()); + } else if (p1.get().toString().equals(PRIORITY_HIGH)) { return 1; - } else if (p2.get().toString().equals(PriorityTagType.HIGH.toString())) { + } else if (p2.get().toString().equals(PRIORITY_HIGH)) { return -1; - } else if (p2.get().toString().equals(PriorityTagType.LOW.toString())) { + } else if (p2.get().toString().equals(PRIORITY_LOW)) { return 1; } else { return -1; From 772c92111c135f9485007bd11c0707810dde8f43 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Tue, 29 Mar 2022 15:48:55 +0800 Subject: [PATCH 08/21] Update sorting logic - Removed sorting using FilteredApplicationList class - Added sorting methods using InternApplyMemory class --- .../address/logic/commands/ListCommand.java | 42 ++++++++----------- .../logic/parser/ListCommandParser.java | 4 +- .../address/model/InternApplyMemory.java | 9 ++++ src/main/java/seedu/address/model/Model.java | 8 ++-- .../seedu/address/model/ModelManager.java | 17 ++++---- .../application/UniqueApplicationList.java | 15 +++++++ 6 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index a9b32a7d141..3028aaaac63 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -3,16 +3,14 @@ import static java.util.Objects.requireNonNull; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_APPLICATIONS; -import javafx.collections.transformation.FilteredList; +import java.util.Comparator; +import java.util.Optional; + import seedu.address.logic.sort.InterviewSlotComparator; import seedu.address.logic.sort.NameComparator; import seedu.address.logic.sort.PriorityComparator; import seedu.address.model.Model; import seedu.address.model.application.Application; -import seedu.address.model.application.NameContainsKeywordsPredicate; - -import java.util.Comparator; -import java.util.Optional; /** * Lists all applications in InternApply to the user. @@ -29,24 +27,29 @@ public class ListCommand extends Command { // TODO: Update it to variable as per edit public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Show a filtered list of all applications with the " - + "selected parameter.\n" - + "Parameters: [FIELD " - + NameComparator.COMMAND_WORD + "|" - + InterviewSlotComparator.COMMAND_WORD + "|" - + PriorityComparator.COMMAND_WORD + " " - + "[ORDER " + COMMAND_ORDER_WORD_ASCENDING + "|" + COMMAND_ORDER_WORD_DESCENDING + "] \n" + + ": Show a sorted list of all applications with the given sort parameter.\n" + + "Parameters: [parameter " + + NameComparator.COMMAND_WORD.toUpperCase() + "|" + + InterviewSlotComparator.COMMAND_WORD.toUpperCase() + "|" + + PriorityComparator.COMMAND_WORD.toUpperCase() + "] " + + "[order " + COMMAND_ORDER_WORD_ASCENDING + "|" + COMMAND_ORDER_WORD_DESCENDING + "] \n" + "Example: " + COMMAND_WORD + " INTERVIEW " + COMMAND_ORDER_WORD_DESCENDING + "\n" - + "Note: For default listing use " + COMMAND_WORD + " [ORDER] without the sorting field."; + + "Note: Using list without parameters will revert to the last sorted."; private final Optional> sortingComparator; private final String orderBy; + /** + * Creates a ListCommand with the previous sorting order. + */ public ListCommand() { sortingComparator = Optional.empty(); orderBy = COMMAND_ORDER_WORD_ASCENDING; } + /** + * Creates a ListCommand with a specified {@code sortingComparator} and {@code orderBy} + */ public ListCommand(Comparator sortingComparator, String orderBy) { this.sortingComparator = Optional.ofNullable(sortingComparator); this.orderBy = orderBy; @@ -55,19 +58,8 @@ public ListCommand(Comparator sortingComparator, String orderBy) { @Override public CommandResult execute(Model model) { requireNonNull(model); + sortingComparator.ifPresent(applicationComparator -> model.sortApplications(applicationComparator, orderBy)); model.updateFilteredApplicationList(PREDICATE_SHOW_ALL_APPLICATIONS); - - FilteredList filteredApplications = new FilteredList<>(model - .getInternApplyMemory().getApplicationList()); - - if (sortingComparator.isEmpty()) { - model.setFilteredApplicationList(filteredApplications); - } else { -// filteredApplications.sort(sortingComparator.get()); -// model.setFilteredApplicationList(filteredApplications); - System.out.println("ok"); - model.getFilteredApplicationList().sort(sortingComparator.get()); - } return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/seedu/address/logic/parser/ListCommandParser.java b/src/main/java/seedu/address/logic/parser/ListCommandParser.java index d031a7864a2..ef304692765 100644 --- a/src/main/java/seedu/address/logic/parser/ListCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/ListCommandParser.java @@ -37,8 +37,8 @@ public ListCommand parse(String args) throws ParseException { return new ListCommand(); } } else { - String sortingField = sortingArgs[0]; - String orderBy = sortingArgs[1]; + String sortingField = sortingArgs[0].toLowerCase(); + String orderBy = sortingArgs[1].toUpperCase(); if (validateOrderBy(orderBy)) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE)); diff --git a/src/main/java/seedu/address/model/InternApplyMemory.java b/src/main/java/seedu/address/model/InternApplyMemory.java index 5be05041cf0..17dac04e2a0 100644 --- a/src/main/java/seedu/address/model/InternApplyMemory.java +++ b/src/main/java/seedu/address/model/InternApplyMemory.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +import java.util.Comparator; import java.util.List; import javafx.collections.ObservableList; @@ -38,6 +39,14 @@ public InternApplyMemory(ReadOnlyInternApplyMemory toBeCopied) { } //// list overwrite operations + /** + * Replaces the order of the application list with {@code c} and order by {@code orderBy}. + * */ + public void sortApplications(Comparator c, String orderBy) { + requireNonNull(c); + requireNonNull(orderBy); + this.applications.sort(c, orderBy); + } /** * Replaces the contents of the application list with {@code applications}. diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 606d8f523de..faff8b36486 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -1,10 +1,10 @@ package seedu.address.model; import java.nio.file.Path; +import java.util.Comparator; import java.util.function.Predicate; import javafx.collections.ObservableList; -import javafx.collections.transformation.FilteredList; import seedu.address.commons.core.GuiSettings; import seedu.address.model.application.Application; @@ -18,9 +18,7 @@ public interface Model { /** {@code Predicate} that returns true if the application's interview slot falls with a week of the local date on * the local machine. */ - Predicate PREDICATE_SHOW_UPCOMING_APPLICATIONS_ONLY = application -> { - return application.isUpcomingInterview(); - }; + Predicate PREDICATE_SHOW_UPCOMING_APPLICATIONS_ONLY = Application::isUpcomingInterview; /** * Replaces user prefs data with the data in {@code userPrefs}. @@ -104,5 +102,5 @@ public interface Model { */ void updateUpcomingApplicationList(Predicate predicate); - void setFilteredApplicationList(FilteredList filteredApplications); + void sortApplications(Comparator c, String orderBy); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 9efc7e467b2..7c24a97be7f 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -4,6 +4,7 @@ import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.nio.file.Path; +import java.util.Comparator; import java.util.function.Predicate; import java.util.logging.Logger; @@ -112,10 +113,17 @@ public void addApplication(Application application) { @Override public void setApplication(Application target, Application editedApplication) { requireAllNonNull(target, editedApplication); - internApplyMemory.setApplication(target, editedApplication); } + //=========== Sorting Application List Accessors ======================================================== + @Override + public void sortApplications(Comparator c, String orderBy) { + requireNonNull(c); + requireNonNull(orderBy); + internApplyMemory.sortApplications(c, orderBy); + } + //=========== Filtered Application List Accessors ======================================================== /** @@ -150,13 +158,6 @@ public void updateUpcomingApplicationList(Predicate predicate) { upcomingApplications.setPredicate(predicate); } - @Override - public void setFilteredApplicationList(FilteredList filteredApplications) { - requireNonNull(filteredApplications); - //this.filteredApplications.clear(); - //this.filteredApplications.addAll(filteredApplications); - } - @Override public boolean equals(Object obj) { // short circuit if same object diff --git a/src/main/java/seedu/address/model/application/UniqueApplicationList.java b/src/main/java/seedu/address/model/application/UniqueApplicationList.java index 2ffc4c83fdd..50f29b910e7 100644 --- a/src/main/java/seedu/address/model/application/UniqueApplicationList.java +++ b/src/main/java/seedu/address/model/application/UniqueApplicationList.java @@ -3,11 +3,14 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import seedu.address.logic.commands.ListCommand; import seedu.address.model.application.exceptions.ApplicationNotFoundException; import seedu.address.model.application.exceptions.DuplicateApplicationException; @@ -28,6 +31,18 @@ public class UniqueApplicationList implements Iterable { private final ObservableList internalList = FXCollections.observableArrayList(); private final ObservableList internalUnmodifiableList = FXCollections.unmodifiableObservableList(internalList); + /** + * Sort the application list according to the given sorting argument. + * */ + public void sort(Comparator c, String orderBy) { + requireNonNull(c); + requireNonNull(orderBy); + if (orderBy.equals(ListCommand.COMMAND_ORDER_WORD_ASCENDING)) { + internalList.sort(c); + } else { + internalList.sort(Collections.reverseOrder(c)); + } + } /** * Returns true if the list contains an equivalent application as the given argument. From 8700f44eb2c2f2e3d4911fa197f438af4aa04102 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Tue, 29 Mar 2022 15:49:20 +0800 Subject: [PATCH 09/21] Update PriorityTag getter --- .../java/seedu/address/model/application/Application.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/address/model/application/Application.java b/src/main/java/seedu/address/model/application/Application.java index 76f70934887..c3e549723e6 100644 --- a/src/main/java/seedu/address/model/application/Application.java +++ b/src/main/java/seedu/address/model/application/Application.java @@ -8,8 +8,8 @@ import java.util.Optional; import java.util.Set; -import seedu.address.model.tag.PriorityTag; import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagType; /** * Represents an Application in InternApply. @@ -81,10 +81,10 @@ public Details getDetails() { return details; } - public Optional getPriorityTag() { + public Optional getPriorityTag() { for (Tag tag: tags) { - if (tag instanceof PriorityTag) { - return Optional.of((PriorityTag) tag); + if (tag.tagType.equals(TagType.PRIORITY)) { + return Optional.of(tag); } } return Optional.empty(); From c264fd3b9d99a6e5d5ddd3978fe977b9b6445b85 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Tue, 29 Mar 2022 15:56:54 +0800 Subject: [PATCH 10/21] Update ListCommand test cases --- .../java/seedu/address/logic/commands/AddCommandTest.java | 6 ++++++ .../seedu/address/logic/parser/InternApplyParserTest.java | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 025b14c4964..9d249285d93 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -9,6 +9,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -158,6 +159,11 @@ public ObservableList getUpcomingApplicationList() { public void updateUpcomingApplicationList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + + @Override + public void sortApplications(Comparator c, String orderBy) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/parser/InternApplyParserTest.java b/src/test/java/seedu/address/logic/parser/InternApplyParserTest.java index 9ea25714909..dfb653df48d 100644 --- a/src/test/java/seedu/address/logic/parser/InternApplyParserTest.java +++ b/src/test/java/seedu/address/logic/parser/InternApplyParserTest.java @@ -23,6 +23,7 @@ import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.logic.sort.NameComparator; import seedu.address.model.application.Application; import seedu.address.model.application.NameContainsKeywordsPredicate; import seedu.address.testutil.ApplicationBuilder; @@ -88,7 +89,8 @@ public void parseCommand_help() throws Exception { @Test public void parseCommand_list() throws Exception { assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand); - assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand); + assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " " + NameComparator.COMMAND_WORD + " " + + ListCommand.COMMAND_ORDER_WORD_ASCENDING + " 1") instanceof ListCommand); } @Test From bb0a492bffc9cdb4394ad32f2a58e88d33f84679 Mon Sep 17 00:00:00 2001 From: Lee Yong Ler Date: Tue, 29 Mar 2022 23:31:22 +0800 Subject: [PATCH 11/21] Update UG to be more user friendly --- docs/UserGuide.md | 180 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 136 insertions(+), 44 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 11145db8044..159f22aa92f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -5,25 +5,37 @@ title: User Guide SoC InternApply (SIA) is a **desktop app for managing internship applications, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, SIA can get your internship application management tasks done faster than traditional GUI apps. +With SoC InternApply, you can easily add an application, edit it later on if there are any changes needed, find the applications based on keywords and also sort them based on priority, interview date and much more! All while not having to worry about saving or storing your applications as this is done internally and automatically by SoC InternApply. + +Ultimately, with SoC InternApply, you can worry less about the administrative tasks and focus more on preparing for the interviews themselves! + +## Table of Contents * Table of Contents - {:toc} +{:toc} + +-------------------------------------------------------------------------------------------------------------------- +## Glossary +1. SIA (SoC InternApply) + +[Go To TOC](#table-of-contents) -------------------------------------------------------------------------------------------------------------------- ## Quick start -1. Ensure you have Java `11` or above installed in your Computer. +1. Ensure you have Java `11` or above installed in your Computer. You can download it from [this website](https://www.oracle.com/sg/java/technologies/javase/jdk11-archive-downloads.html). 2. Download the latest `internapply.jar` from [here](https://github.com/AY2122S2-CS2103T-T11-3/tp/releases). -3. Copy the file to the folder you want to use as the _home folder_ for your SIA. +3. Copy the file to the folder you want to use as the _root folder_ for your SIA (e.g. you can save it in your desktop or downloads folder).
+**Note:** There will be data (your internship applications) stored into this same folder, but it would not take up much space. + +4. Double-click the jar file to start the app. The GUI similar to the diagram below should appear in a few seconds. Note how the app contains some sample data.

-4. Double-click the jar file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
![Ui](images/MainWindowUi.png) -5. Another window should appear similar to the below. Note that this window **would contain any upcoming interviews you have in a weeks time**.
+5. Another reminder window should appear automatically similar to the below. Note that this window **would contain any upcoming interviews you have in a weeks time**.
![Ui](images/ReminderWindowUi.png) - 6. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try: * **`help`** : Shows a message explaining how to access the help page. @@ -48,6 +60,8 @@ SoC InternApply (SIA) is a **desktop app for managing internship applications, o 7. Refer to the [Features](#features) below for details of each command. +[Go To TOC](#table-of-contents) + -------------------------------------------------------------------------------------------------------------------- ## Features @@ -62,6 +76,24 @@ SoC InternApply (SIA) is a **desktop app for managing internship applications, o * Items in square brackets are optional.
e.g `n/NAME [t/TAG]` can be used as `n/Grab SG t/local` or as `n/Grab SG`. +* Items with `…`​ after them can be used multiple times including zero times.
+ e.g. `[t/TAG]…​` can be used as ` ` (i.e. 0 times), `t/local` or `t/local t/NUS` etc. + +* Parameters can be in any order.
+ e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. + +* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence of the parameter will be taken.
+ e.g. if you specify `j/Software Engineer j/Data Scientist`, only `j/Data Scientist` will be taken. + +* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `reminder`, `exit` and `clear`) will be ignored.
+ e.g. if the command specifies `help 123`, it will be interpreted as `help`. + + +**:information_source: Notes about the input format:**
+ +* For `[t/TAG]...`, only alphanumeric inputs are allowed. i.e. Only the characters A-Z, a-z, 0-9.
+ e.g. `t/Based In Singapore` is not allowed, `t/BasedInSingapore` is allowed. + * For `[pt/PRIORITY_TAG]`, user input can only be any one of these: `HIGH`, `MEDIUM`, `LOW`
e.g `pt/HIGH` can be used to set priority of an application to `HIGH` @@ -71,30 +103,31 @@ SoC InternApply (SIA) is a **desktop app for managing internship applications, o * For `[pt/PRIORITY_TAG]` and `[ast/APPLICATION_STATUS_TAG]`, the inputs are case-insensitive
e.g. `pt/HIGH` can be inputted with `pt/high` and `ast/INTERVIEWD` can be inputted with `ast/Interviewed` -* For `[t/TAG]...`, only alphanumeric inputs are allowed. i.e. Only the characters A-Z, a-z, 0-9.
- e.g. `t/Based In Singapore` is not allowed, `t/BasedInSingapore` is allowed. - -* Items with `…`​ after them can be used multiple times including zero times.
- e.g. `[t/TAG]…​` can be used as ` ` (i.e. 0 times), `t/local`, `t/local t/NUS` etc. +* For `[j/JobTitle]...`, only alphanumeric inputs are allowed. i.e. Only the characters A-Z, a-z, 0-9. Spaces are also allowed.
+ e.g. `j/SoftwareEngineerIntern` is allowed, `t/Software Engineer Intern` is also allowed. -* Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. -* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence of the parameter will be taken.
- e.g. if you specify `j/Software Engineer j/Data Scientist`, only `j/Data Scientist` will be taken. - -* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `reminder`, `exit` and `clear`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`. +[Go To TOC](#table-of-contents) + ### Viewing help : `help` -Shows a message explaining how to access the help page. +This command displays a message explaining how to access the help page. +Format: `help` + +Example usages: + +`help` + +Expected outcome: + +A pop up window showing a link to the help page, as shown below. ![helpMessage](images/helpMessage.png) -Format: `help` +[Go To TOC](#table-of-contents) ### Adding an application: `add` @@ -102,50 +135,87 @@ Adds an application to SoC InternApply. Format: `add n/NAME_OF_COMPANY j/JOB_TITLE p/PHONE_NUMBER a/ADDRESS e/EMAIL [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]` -**Note:** `[t/TAG]`, `[pt/PRIORITY_TAG]` and `[ast/APPLICATION_STATUS_TAG]` are optional. +**Note:** `NAME_OF_COMPANY` has to be unique. +**Note:** `[t/TAG]`, `[pt/PRIORITY_TAG]` and `[ast/APPLICATION_STATUS_TAG]` are optional. -Examples: +Example usages and expected outcomes: * `add n/Shopee j/Software Engineer Intern p/87438807 e/hr@shopee.sg a/5 Science Park Dr, #06-40 t/SoftwareEngineering ` + +Feedback message: +``` +New application added: Shopee; Job Title: Software Engineer Intern; Phone: 87438807; Email: hr@shopee.sg; Address: 5 Science Park Dr, #06-40; Interview Slot: Interview date is not set.; Details: To add details, use the edit command; Tags: SoftwareEngineering +``` + * `add n/Shopee j/Software Engineer Intern p/87438807 e/hr@shopee.sg a/5 Science Park Dr, #06-40 t/SoftwareEngineering pt/HIGH ast/NOT_APPLIED` +Feedback message: +``` +This application already exists in InternApply +``` + + +[Go To TOC](#table-of-contents) + ### Listing all applications : `list` Shows a list of all applications in SoC InternApply. Format: `list` + +[Go To TOC](#table-of-contents) + ### Listing applications with upcoming interviews: `reminder` Shows a list of applications with upcoming interviews, falling within a week from now, in SoC InternApply. Format: `reminder` +Example usages: + +`reminder` + +Expected outcome: + +A new window pops up, showing a list of applications with upcoming interviews within a week from now. + +[Go To TOC](#table-of-contents) + ### Editing an application : `edit` Edits an existing application in SoC InternApply. Format: `edit INDEX [n/NAME] [j/JOB_TITLE] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [idt/INTERVIEW_DATE_TIME] [d/DETAILS] [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]` + +**CAUTION:** The `edit` command might overwrite your existing application data. +
- Edits the application at the specified `INDEX`. The index refers to the index number shown in the displayed application list. The index **must be a positive integer** 1, 2, 3, ... - At least one of the optional fields must be provided. - Existing values will be updated to the input values. - You can add an interview slot that includes both date and time by using the `idt/INTERVIEW_DATE_TIME` -- The interview date time, `INTERVIEW_DATE_TIME`, must in the follow format `dd-MM-yyyy HH:mm`. +- The interview date time, `INTERVIEW_DATE_TIME`, must be in the follow format `dd-MM-yyyy HH:mm`. - You can add details to the application by using `d/DETAILS` - You can enter new lines in the details by using `\n` - You can remove `INTERVIEW_DATE_TIME` by typing `idt/` without specifying any tags after it. -- When editing `TAG`'s, the `TAG`'s that are not specified by the user will be filled in using the corresponding `TAG`'s within the existing application. +- When editing the `TAG` field, if `t/` is given without any input, the existing tags will be reused and not deleted. -Examples: +Example usages and expected outcomes: - `edit 1 e/SoCStudent@example.com n/NUS Research` Edits the email and name of the 1st application to be `SoCStudent@example.com` and `NUS Research` respectively. -- `edit 1 t/Singapore ast/APPLIED` Edits the tags and application status tag of the 1st application to Singapore and APPLIED respectively. Since the priority tag is not specified, the 1st application will keep it's current priority tag if it had any. +- `edit 1 t/Singapore ast/APPLIED` Edits the tags and application status tag of the 1st application to Singapore and APPLIED respectively. Since the priority tag is not specified, the 1st application will keep its current priority tag if it had any. - `edit 2 j/Intern idt/` Edits the job title of the 2nd application to be `Intern` and clears the existing interview date time. -- `edit 1 d/Example details \nThis is a newline of the details` Edits the details to be: + +- To edit the details of an application, you can follow this format (adding \n to type in a new line): `edit 1 d/Example details \nThis is a newline of the details` + +e.g.`edit 1 d/This company requires a preliminary coding round.\n I should practice more on HackerRank` will result in this details being added: + ``` -Example details -This is a newline of the details +This company requires a preliminary coding round. +I should practice more on HackerRank ``` +[Go To TOC](#table-of-contents) + ### Deleting an application : `delete` Deletes the specified application from SoC InternApply. @@ -156,9 +226,15 @@ Format: `delete INDEX` * The index refers to the index number shown in the displayed application list. * The index **must be a positive integer** 1, 2, 3, …​ -Examples: +Example usages: * `list` followed by `delete 2` deletes the 2nd application. +Expected outcome: + +The previous 2nd application is removed from the storage and a new list of applications is shown. + +[Go To TOC](#table-of-contents) + ### Finding application(s) : `find` Find existing applications in SoC InternApply. @@ -169,14 +245,15 @@ Format: `find [n/NAME] or find [j/JOB_TITLE] or find [t/TAG]... or find [pt/PRIO - Parameters are only expected once (except tags). e.g. `find n/shopee n/grab` is equivalent to `find n/grab`, the last occurrence of the parameter will be taken. - If more than 1 different fields are given, i.e. `find n/shopee j/ML`, only the first field will be processed, i.e. `find n/shopee j/ML` is the same as `find n/shopee` -Examples: +Example usages and expected outcomes: - `find n/shopee` finds and displays all applications with "shopee" in its name. - `find j/ML` finds and displays all applications with "ML" in its job title. - `find pt/HIGH` finds and displays all applications with "HIGH" in its priority tag. - `find ast/applied` finds and displays all applications with "applied" in its application status. (note that it is case-insensitive) - `find t/overseas` finds and displays all applications with "overseas" in its tags. -- `find t/overseas t/USA` finds and displays all applications with "overseas" and "USA" in its tags. +- `find t/overseas t/USA` finds and displays all applications with "overseas" or "USA" in its tags. +[Go To TOC](#table-of-contents) ### Clearing all applications : `clear` @@ -184,27 +261,39 @@ Clears all applications from SoC InternApply. Format: `clear` +[Go To TOC](#table-of-contents) + ### Exiting the program : `exit` Exits the program. Format: `exit` +[Go To TOC](#table-of-contents) + ### Saving the data InternApply data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. +[Go To TOC](#table-of-contents) + +### Extra features _More features coming soon ..._ -------------------------------------------------------------------------------------------------------------------- ## FAQ +**Q**: How do I know where my internship applications data is stored?
+**A**: Please locate where SoC InternApply is being stored on your computer. You will see a folder named `data` found in the root folder of the application (the folder containing SoC InternApply) Inside the `data` folder, you can find a data file named `internapplymemory.json`, which stores all the applications. -**Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous SoC InternApply home folder.
+**Q**: How do I transfer my data to another computer?
+**A**: Refer to the 1st QnA to locate the data file. Install the app in the other computer. Copy the contents of the data file of SoC InternApply from your previous computer and paste it in the empty data file of SoC InternApply of the new computer.
**Q**: When I run SIA for the first time, I do not see any of the sample application. How can I get the sample applications to appear in SIA?
-**A**: Please locate where InternApply data is being stored on your hard disk. This will usually be in a folder named `data` found in the root folder of the application. Delete any existing files in that folder and run SoC InternApply again. +**A**: Refer to the 1st QnA to locate the `data` folder. Delete any existing files in the `data` folder and run SoC InternApply again. + + +[Go To TOC](#table-of-contents) -------------------------------------------------------------------------------------------------------------------- @@ -212,12 +301,15 @@ _More features coming soon ..._ Action | Format, Examples --------|------------------ -**Help** | `help` -**List** | `list` -**Reminder**| `reminder` -**Add** | `add n/NAME_OF_COMPANY p/PHONE_NUMBER a/ADDRESS j/JOB_TITLE e/EMAIL [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]`
e.g., `add n/Singtel j/UIUX Intern p/62527525 e/singtel@sg.com a/Singtel Group Strategic Communications and Brand, 31 Exeter Road, Comcentre #19-00 ast/APPLIED` -**Edit** | `edit INDEX [n/NAME] [j/JOB_TITLE] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [idt/INTERVIEW_DATE_TIME] [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]`
e.g, `edit 1 n/Grab SG p/65358292 idt/17-03-2022 13:30` -**Delete** | `delete INDEX`
e.g., `delete 3` -**Find** | `find [n/NAME] or find [j/JOB_TITLE] or find [t/TAG]... or find [pt/PRIORITY_TAG] or find [ast/APPLICATION_STATUS_TAG]`
e.g., `find n/shopee` -**Clear** | `clear` -**Exit** | `exit` +[**Add**](#adding-an-application) | `add n/NAME_OF_COMPANY p/PHONE_NUMBER a/ADDRESS j/JOB_TITLE e/EMAIL [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]`

e.g., `add n/Singtel j/UIUX Intern p/62527525 e/singtel@sg.com a/Singtel Group Strategic Communications and Brand, 31 Exeter Road, Comcentre #19-00 ast/APPLIED` +[**Delete**](deleting-an-application) | `delete INDEX`

e.g., `delete 3` +[**Clear**](clearing-all-applications) | `clear` +[**Edit**](exit) | `edit INDEX [n/NAME] [j/JOB_TITLE] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [idt/INTERVIEW_DATE_TIME] [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]`

e.g, `edit 1 n/Grab SG p/65358292 idt/17-03-2022 13:30` +[**Exit**](exiting-the-program) | `exit` +[**Find**](finding-application(s)) | `find [n/NAME] or find [j/JOB_TITLE] or find [t/TAG]... or find [pt/PRIORITY_TAG] or find [ast/APPLICATION_STATUS_TAG]`

e.g., `find n/shopee` +[**Help**](viewing-help) | `help` +[**List**](listing-all-applications) | `list` +[**Reminder**](listing-applications-with-upcoming-interviews)| `reminder` + + +[Go To TOC](#table-of-contents) From 8a3451357b0fe958dc8ecba9e27db1f909ca8339 Mon Sep 17 00:00:00 2001 From: Lee Yong Ler Date: Tue, 29 Mar 2022 23:35:27 +0800 Subject: [PATCH 12/21] Fix Ui.png wrong name --- docs/DeveloperGuide.md | 2 +- docs/images/{Ui-after-details-update.png => Ui.png} | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/images/{Ui-after-details-update.png => Ui.png} (100%) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 46dd5839b1d..2d83a25c98d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -242,7 +242,7 @@ To display the new `details` field, modifications to the `applicationCard.java` Below is an image of the UI after the changes were made: -![Ui-after-details-update](images/Ui-after-details-update.png) +![Ui-after-details-update](images/Ui.png) #### Proposed improvements 1. As the colour of each `application card` alternates between each index, changes to the `Ui` have to be made as well to match the alternating colours. To achieve this change, implementing the css style in `DarkTheme.css` file, in particular `List-view` css should be made when implementing changes to the `applicationCard.fxml` diff --git a/docs/images/Ui-after-details-update.png b/docs/images/Ui.png similarity index 100% rename from docs/images/Ui-after-details-update.png rename to docs/images/Ui.png From 7635254ba0502d2dc300cabb28e16ca9f6e0a258 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Wed, 30 Mar 2022 04:34:04 +0800 Subject: [PATCH 13/21] Add sorting logic for ApplicationStatus - Added getter for ApplicationStatusTag - Added comparator for ApplicationStatusTag --- .../sort/ApplicationStatusComparator.java | 41 +++++++++++++++++++ .../model/application/Application.java | 9 ++++ 2 files changed, 50 insertions(+) create mode 100644 src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java diff --git a/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java b/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java new file mode 100644 index 00000000000..849921f9cf4 --- /dev/null +++ b/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java @@ -0,0 +1,41 @@ +package seedu.address.logic.sort; + +import static seedu.address.model.tag.ApplicationStatusTagType.ACCEPTED; +import static seedu.address.model.tag.ApplicationStatusTagType.APPLIED; +import static seedu.address.model.tag.ApplicationStatusTagType.INTERVIEWED; +import static seedu.address.model.tag.ApplicationStatusTagType.NOT_APPLIED; +import static seedu.address.model.tag.ApplicationStatusTagType.REJECTED; + +import java.util.Comparator; +import java.util.Optional; + +import seedu.address.model.application.Application; +import seedu.address.model.tag.Tag; + +public class ApplicationStatusComparator implements Comparator { + + public static final String COMMAND_WORD = "status"; + + @Override + public int compare(Application o1, Application o2) { + return getStatusRanking(o1.getApplicationStatusTag()) - getStatusRanking(o2.getApplicationStatusTag()); + } + + private int getStatusRanking(Optional t) { + if (t.isEmpty()) { + return 1; + } else if (t.get().toString().equals(NOT_APPLIED.toString())) { + return 2; + } else if (t.get().toString().equals(APPLIED.toString())) { + return 3; + } else if (t.get().toString().equals(INTERVIEWED.toString())) { + return 4; + } else if (t.get().toString().equals(REJECTED.toString())) { + return 5; + } else if (t.get().toString().equals(ACCEPTED.toString())) { + return 6; + } else { + return 0; + } + } +} diff --git a/src/main/java/seedu/address/model/application/Application.java b/src/main/java/seedu/address/model/application/Application.java index c3e549723e6..46c1ba3032d 100644 --- a/src/main/java/seedu/address/model/application/Application.java +++ b/src/main/java/seedu/address/model/application/Application.java @@ -90,6 +90,15 @@ public Optional getPriorityTag() { return Optional.empty(); } + public Optional getApplicationStatusTag() { + for (Tag tag: tags) { + if (tag.tagType.equals(TagType.APPLICATION_STATUS)) { + return Optional.of(tag); + } + } + return Optional.empty(); + } + /** * Returns an immutable tag set, which throws {@code UnsupportedOperationException} * if modification is attempted. From 441835e4ca09e1304f55c75e0ca5855ddeed6488 Mon Sep 17 00:00:00 2001 From: lchokhoe Date: Wed, 30 Mar 2022 12:32:44 +0800 Subject: [PATCH 14/21] Update SampleData to contain more sensible data that would better serve as an example of how users can make use of SIA. --- .../address/model/util/SampleDataUtil.java | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 7a13e11cc94..4f427e220f2 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -31,41 +31,50 @@ public static Application[] getSampleApplications() { new Phone("87438807"), new Email("hr@shopee.sg"), new Address("5 Science Park Dr, #06-40"), - new InterviewSlot(), - new Details(), - getTagSet("singapore", "HIGH", "INTERVIEWED")), + new InterviewSlot(today.minusDays(7).format(formatter)), + new Details("Applied 2 weeks ago, waiting for a response.\n" + + "OMG! They replied! Will be interviewed this week!\n" + + "Preparing for the interview with Alice and Bob.\n" + + "Interview done, waiting for response...\n" + + "I GOT IN~"), + getTagSet("BasedInSingapore", "HIGH", "ACCEPTED")), new Application(new Name("Grab Holdings Singapore"), new JobTitle("AI Engineer"), new Phone("99272758"), new Email("hr@grab.sg"), new Address("3 Media Cl, #07-18"), - new InterviewSlot(today.minusDays(1).format(formatter)), - new Details(), - getTagSet("colleagues", "friends", "MEDIUM", "APPLIED")), + new InterviewSlot(today.plusDays(1).format(formatter)), + new Details("Alice and Bob was interested in this company so they asked me to join in." + + " Hopefully all goes well and I get accepted (The interview was really tough)..."), + getTagSet( "WithFriends", "MEDIUM", "INTERVIEWED")), new Application(new Name("Microsoft"), new JobTitle("Software Engineer Intern"), new Phone("93210283"), new Email("hr@microsoft.com"), new Address("182 Cecil St, #13-01"), - new InterviewSlot(today.plusDays(1).format(formatter)), - new Details(), - getTagSet("overseas", "LOW", "NOT_APPLIED")), + new InterviewSlot(today.plusDays(7).format(formatter)), + new Details("Microsoft interview preparations:\n" + + "1. Work on LeetCode\n" + + "2. Look for tips on the internet\n" + + "3. Make sure to dress smartly for the interview\n" + + "4. Do your best!"), + getTagSet("DreamJob", "HIGH", "APPLIED")), new Application(new Name("Aftershock PC"), new JobTitle("Data Scientist"), new Phone("63458727"), new Email("corpsales@sg.aftershockpc.com"), new Address("994, Bendemeer Rd, #05-07"), - new InterviewSlot(today.plusDays(7).format(formatter)), + new InterviewSlot(today.plusDays(8).format(formatter)), new Details(), - getTagSet("passion", "HIGH", "APPLIED")), + getTagSet("PassionForPCBuilding", "PossibleOption", "MEDIUM", "NOT_APPLIED")), new Application(new Name("Google Asia Pacific"), new JobTitle("ML Engineer"), new Phone("91031282"), new Email("hr@google.com"), new Address("70 Pasir Panjang Rd, #16-43"), - new InterviewSlot(today.plusDays(8).format(formatter)), + new InterviewSlot(), new Details(), - getTagSet("family", "LOW", "REJECTED")), + getTagSet("HotJob", "LOW", "REJECTED")), }; } From 0d0086cac9c9e67e355a7af232d35558d534d20b Mon Sep 17 00:00:00 2001 From: lchokhoe Date: Wed, 30 Mar 2022 12:39:06 +0800 Subject: [PATCH 15/21] Update ParserUtil#parseTags() method. Currently, the method simply checks if the Collection of Strings passed to it is null or not. This means that even a Collection of empty Set would pass this check as a valid input. Let's change this since an empty Set not be meaningful and should be rejected. We simply include an if-else statement that determines if the Collection passed in is an empty Set. EditCommandParserTest#parse_resetTags_success() has been changed to parse_resetTags_failure() since the behavior that it is testing for no longer exists and "t/" as an empty input is now invalid. --- .../address/logic/parser/ParserUtil.java | 4 ++++ .../logic/parser/EditCommandParserTest.java | 22 +++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index a4ab50f9a67..83f56870489 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -4,6 +4,7 @@ import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -214,6 +215,9 @@ public static Tag parsePriorityTag(String tag) throws ParseException { */ public static Set parseTags(Collection tags) throws ParseException { requireNonNull(tags); + if (tags.equals(Collections.emptySet())) { + throw new ParseException(Tag.MESSAGE_CONSTRAINTS); + } final Set tagSet = new HashSet<>(); for (String tagName : tags) { tagSet.add(parseTag(tagName)); diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java index acbd9d2660d..967de7b3715 100644 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java @@ -115,6 +115,17 @@ public void parse_invalidValue_failure() { Name.MESSAGE_CONSTRAINTS); } + @Test + public void parse_resetTags_failure() { + Index targetIndex = INDEX_THIRD_APPLICATION; + String userInput = targetIndex.getOneBased() + TAG_EMPTY; + + EditApplicationDescriptor descriptor = new EditApplicationDescriptorBuilder().withTags().build(); + EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); + + assertParseFailure(parser, userInput, Tag.MESSAGE_CONSTRAINTS); + } + @Test public void parse_allFieldsSpecified_success() { Index targetIndex = INDEX_SECOND_APPLICATION; @@ -218,15 +229,4 @@ public void parse_invalidValueFollowedByValidValue_success() { expectedCommand = new EditCommand(targetIndex, descriptor); assertParseSuccess(parser, userInput, expectedCommand); } - - @Test - public void parse_resetTags_success() { - Index targetIndex = INDEX_THIRD_APPLICATION; - String userInput = targetIndex.getOneBased() + TAG_EMPTY; - - EditApplicationDescriptor descriptor = new EditApplicationDescriptorBuilder().withTags().build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - - assertParseSuccess(parser, userInput, expectedCommand); - } } From 12381ec62f5d2befa2a95bc65ffb3d1163df27dd Mon Sep 17 00:00:00 2001 From: lchokhoe Date: Wed, 30 Mar 2022 12:41:12 +0800 Subject: [PATCH 16/21] Update to meet checkstylemain requirements. --- .../address/model/util/SampleDataUtil.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 4f427e220f2..bd3b24a5672 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -32,11 +32,11 @@ public static Application[] getSampleApplications() { new Email("hr@shopee.sg"), new Address("5 Science Park Dr, #06-40"), new InterviewSlot(today.minusDays(7).format(formatter)), - new Details("Applied 2 weeks ago, waiting for a response.\n" + - "OMG! They replied! Will be interviewed this week!\n" + - "Preparing for the interview with Alice and Bob.\n" + - "Interview done, waiting for response...\n" + - "I GOT IN~"), + new Details("Applied 2 weeks ago, waiting for a response.\n" + + "OMG! They replied! Will be interviewed this week!\n" + + "Preparing for the interview with Alice and Bob.\n" + + "Interview done, waiting for response...\n" + + "I GOT IN~"), getTagSet("BasedInSingapore", "HIGH", "ACCEPTED")), new Application(new Name("Grab Holdings Singapore"), new JobTitle("AI Engineer"), @@ -44,8 +44,8 @@ public static Application[] getSampleApplications() { new Email("hr@grab.sg"), new Address("3 Media Cl, #07-18"), new InterviewSlot(today.plusDays(1).format(formatter)), - new Details("Alice and Bob was interested in this company so they asked me to join in." + - " Hopefully all goes well and I get accepted (The interview was really tough)..."), + new Details("Alice and Bob was interested in this company so they asked me to join in." + + " Hopefully all goes well and I get accepted (The interview was really tough)..."), getTagSet( "WithFriends", "MEDIUM", "INTERVIEWED")), new Application(new Name("Microsoft"), new JobTitle("Software Engineer Intern"), @@ -53,11 +53,11 @@ public static Application[] getSampleApplications() { new Email("hr@microsoft.com"), new Address("182 Cecil St, #13-01"), new InterviewSlot(today.plusDays(7).format(formatter)), - new Details("Microsoft interview preparations:\n" + - "1. Work on LeetCode\n" + - "2. Look for tips on the internet\n" + - "3. Make sure to dress smartly for the interview\n" + - "4. Do your best!"), + new Details("Microsoft interview preparations:\n" + + "1. Work on LeetCode\n" + + "2. Look for tips on the internet\n" + + "3. Make sure to dress smartly for the interview\n" + + "4. Do your best!"), getTagSet("DreamJob", "HIGH", "APPLIED")), new Application(new Name("Aftershock PC"), new JobTitle("Data Scientist"), From 04f6f13c5cb4fa8d1e6c35a63f5824425c6694e7 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Wed, 30 Mar 2022 15:12:21 +0800 Subject: [PATCH 17/21] Update test cases --- src/test/java/seedu/address/logic/LogicManagerTest.java | 3 ++- .../java/seedu/address/logic/commands/CommandTestUtil.java | 2 +- .../java/seedu/address/logic/commands/ListCommandTest.java | 7 +++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index 7701a605598..96ee2ad4bf1 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -8,6 +8,7 @@ import static seedu.address.logic.commands.CommandTestUtil.JOBTITLE_DESC_SHOPEE; import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_SHOPEE; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_SHOPEE; +import static seedu.address.logic.commands.ListCommand.MESSAGE_NO_CHANGE_FULL; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalApplications.SHOPEE; @@ -66,7 +67,7 @@ public void execute_commandExecutionError_throwsCommandException() { @Test public void execute_validCommand_success() throws Exception { String listCommand = ListCommand.COMMAND_WORD; - assertCommandSuccess(listCommand, ListCommand.MESSAGE_SUCCESS, model); + assertCommandSuccess(listCommand, MESSAGE_NO_CHANGE_FULL, model); } @Test diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 98f4a779970..adefa56bbb3 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -91,7 +91,7 @@ public static void assertCommandSuccess(Command command, Model actualModel, Comm Model expectedModel) { try { CommandResult result = command.execute(actualModel); - assertEquals(expectedCommandResult, result); + assertEquals(expectedCommandResult.toString(), result.toString()); assertEquals(expectedModel, actualModel); } catch (CommandException ce) { throw new AssertionError("Execution of command should not fail.", ce); diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java index 59d82bf6757..af4411f7b2b 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java @@ -2,6 +2,7 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.logic.commands.CommandTestUtil.showApplicationAtIndex; +import static seedu.address.logic.commands.ListCommand.MESSAGE_NO_CHANGE_FULL; import static seedu.address.testutil.TypicalApplications.getTypicalInternApplyMemory; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_APPLICATION; @@ -28,12 +29,14 @@ public void setUp() { @Test public void execute_listIsNotFiltered_showsSameList() { - assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel); + assertCommandSuccess(new ListCommand(), model, MESSAGE_NO_CHANGE_FULL, + expectedModel); } @Test public void execute_listIsFiltered_showsEverything() { showApplicationAtIndex(model, INDEX_FIRST_APPLICATION); - assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel); + assertCommandSuccess(new ListCommand(), model, MESSAGE_NO_CHANGE_FULL, + expectedModel); } } From 81a859fb618f9772f28ee7732e5bd518fb1dbeed Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Wed, 30 Mar 2022 15:14:31 +0800 Subject: [PATCH 18/21] Add sorting by ApplicationStatus - Added sorting parser for application status tag - Updated list success message - Change sorting order for application status tag --- .../address/logic/commands/ListCommand.java | 19 +++++++++++++++---- .../logic/parser/ListCommandParser.java | 3 +++ .../sort/ApplicationStatusComparator.java | 17 +++++++++++------ .../logic/sort/InterviewSlotComparator.java | 5 +++++ .../address/logic/sort/NameComparator.java | 5 +++++ .../logic/sort/PriorityComparator.java | 5 +++++ 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 3028aaaac63..3f7f7f2f0fc 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -6,6 +6,7 @@ import java.util.Comparator; import java.util.Optional; +import seedu.address.logic.sort.ApplicationStatusComparator; import seedu.address.logic.sort.InterviewSlotComparator; import seedu.address.logic.sort.NameComparator; import seedu.address.logic.sort.PriorityComparator; @@ -23,15 +24,19 @@ public class ListCommand extends Command { public static final String COMMAND_ORDER_WORD_DESCENDING = "DESC"; - public static final String MESSAGE_SUCCESS = "Listed filtered applications"; - // TODO: Update it to variable as per edit + public static final String MESSAGE_SUCCESS = "Sorted applications by %1$s"; + + public static final String MESSAGE_NO_CHANGE = "last sorted method."; + + public static final String MESSAGE_NO_CHANGE_FULL = String.format(MESSAGE_SUCCESS, MESSAGE_NO_CHANGE); public static final String MESSAGE_USAGE = COMMAND_WORD + ": Show a sorted list of all applications with the given sort parameter.\n" + "Parameters: [parameter " + NameComparator.COMMAND_WORD.toUpperCase() + "|" + InterviewSlotComparator.COMMAND_WORD.toUpperCase() + "|" - + PriorityComparator.COMMAND_WORD.toUpperCase() + "] " + + PriorityComparator.COMMAND_WORD.toUpperCase() + "|" + + ApplicationStatusComparator.COMMAND_WORD.toUpperCase() + "] " + "[order " + COMMAND_ORDER_WORD_ASCENDING + "|" + COMMAND_ORDER_WORD_DESCENDING + "] \n" + "Example: " + COMMAND_WORD + " INTERVIEW " + COMMAND_ORDER_WORD_DESCENDING + "\n" + "Note: Using list without parameters will revert to the last sorted."; @@ -60,6 +65,12 @@ public CommandResult execute(Model model) { requireNonNull(model); sortingComparator.ifPresent(applicationComparator -> model.sortApplications(applicationComparator, orderBy)); model.updateFilteredApplicationList(PREDICATE_SHOW_ALL_APPLICATIONS); - return new CommandResult(MESSAGE_SUCCESS); + return new CommandResult(String.format(MESSAGE_SUCCESS, outputMsg())); + } + + private String outputMsg() { + return sortingComparator.map(applicationComparator -> String.format( + "%s order by %s.", applicationComparator, orderBy.toLowerCase())) + .orElse(MESSAGE_NO_CHANGE); } } diff --git a/src/main/java/seedu/address/logic/parser/ListCommandParser.java b/src/main/java/seedu/address/logic/parser/ListCommandParser.java index ef304692765..905224ac555 100644 --- a/src/main/java/seedu/address/logic/parser/ListCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/ListCommandParser.java @@ -6,6 +6,7 @@ import seedu.address.logic.commands.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.logic.sort.ApplicationStatusComparator; import seedu.address.logic.sort.InterviewSlotComparator; import seedu.address.logic.sort.NameComparator; import seedu.address.logic.sort.PriorityComparator; @@ -48,6 +49,8 @@ public ListCommand parse(String args) throws ParseException { return new ListCommand(new InterviewSlotComparator(), orderBy); } else if (sortingField.equals(PriorityComparator.COMMAND_WORD)) { return new ListCommand(new PriorityComparator(), orderBy); + } else if (sortingField.equals(ApplicationStatusComparator.COMMAND_WORD)) { + return new ListCommand(new ApplicationStatusComparator(), orderBy); } } diff --git a/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java b/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java index 849921f9cf4..612e6a0f58d 100644 --- a/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java +++ b/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java @@ -23,19 +23,24 @@ public int compare(Application o1, Application o2) { private int getStatusRanking(Optional t) { if (t.isEmpty()) { - return 1; + return 6; } else if (t.get().toString().equals(NOT_APPLIED.toString())) { - return 2; + return 5; } else if (t.get().toString().equals(APPLIED.toString())) { - return 3; - } else if (t.get().toString().equals(INTERVIEWED.toString())) { return 4; + } else if (t.get().toString().equals(INTERVIEWED.toString())) { + return 3; } else if (t.get().toString().equals(REJECTED.toString())) { - return 5; + return 2; } else if (t.get().toString().equals(ACCEPTED.toString())) { - return 6; + return 1; } else { return 0; } } + + @Override + public String toString() { + return COMMAND_WORD; + } } diff --git a/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java b/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java index bab0e18d5dd..edcddc4c89d 100644 --- a/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java +++ b/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java @@ -12,4 +12,9 @@ public class InterviewSlotComparator implements Comparator { public int compare(Application o1, Application o2) { return o1.getInterviewSlot().getValue().compareTo(o2.getInterviewSlot().getValue()); } + + @Override + public String toString() { + return COMMAND_WORD; + } } diff --git a/src/main/java/seedu/address/logic/sort/NameComparator.java b/src/main/java/seedu/address/logic/sort/NameComparator.java index 02950ac3aac..48e6e2f6b20 100644 --- a/src/main/java/seedu/address/logic/sort/NameComparator.java +++ b/src/main/java/seedu/address/logic/sort/NameComparator.java @@ -12,4 +12,9 @@ public class NameComparator implements Comparator { public int compare(Application o1, Application o2) { return o1.getName().toString().compareTo(o2.getName().toString()); } + + @Override + public String toString() { + return COMMAND_WORD; + } } diff --git a/src/main/java/seedu/address/logic/sort/PriorityComparator.java b/src/main/java/seedu/address/logic/sort/PriorityComparator.java index e6c40f16f2a..247707a4697 100644 --- a/src/main/java/seedu/address/logic/sort/PriorityComparator.java +++ b/src/main/java/seedu/address/logic/sort/PriorityComparator.java @@ -39,4 +39,9 @@ public int compare(Application o1, Application o2) { } } } + + @Override + public String toString() { + return COMMAND_WORD; + } } From 01393a3ba6992d0d5794d8d883eff7cbedcc2401 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Wed, 30 Mar 2022 19:11:43 +0800 Subject: [PATCH 19/21] Add comments for new methods and constructors --- .../java/seedu/address/logic/commands/ListCommand.java | 1 + .../address/logic/sort/ApplicationStatusComparator.java | 7 +++++++ .../seedu/address/logic/sort/InterviewSlotComparator.java | 4 ++++ src/main/java/seedu/address/logic/sort/NameComparator.java | 4 ++++ .../java/seedu/address/logic/sort/PriorityComparator.java | 6 ++++++ 5 files changed, 22 insertions(+) diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 3f7f7f2f0fc..1f4331b087a 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -46,6 +46,7 @@ public class ListCommand extends Command { /** * Creates a ListCommand with the previous sorting order. + * Notes: the {@code sortingComparator} and {@code orderBy} are just placeholder values. */ public ListCommand() { sortingComparator = Optional.empty(); diff --git a/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java b/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java index 612e6a0f58d..c5ef813dd46 100644 --- a/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java +++ b/src/main/java/seedu/address/logic/sort/ApplicationStatusComparator.java @@ -21,6 +21,13 @@ public int compare(Application o1, Application o2) { return getStatusRanking(o1.getApplicationStatusTag()) - getStatusRanking(o2.getApplicationStatusTag()); } + /** + * Compares the two application's status tag field. Returns a negative integer, zero, or a positive integer as + * the first argument is less than, equal to, or greater than the second base on alphanumeric order. + * The default order from ascending to descend is as follows ACCEPTED, REJECTED, INTERVIEWED, APPLIE and + * NOT_APPLIED. + * An empty tag will be considered as the lowest ranking, ranked below NOT_APPLIED. + * */ private int getStatusRanking(Optional t) { if (t.isEmpty()) { return 6; diff --git a/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java b/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java index edcddc4c89d..97e355b3f75 100644 --- a/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java +++ b/src/main/java/seedu/address/logic/sort/InterviewSlotComparator.java @@ -8,6 +8,10 @@ public class InterviewSlotComparator implements Comparator { public static final String COMMAND_WORD = "interview"; + /** + * Compares the two application's interview slot field. Returns a negative integer, zero, or a positive integer as + * the first argument is less than, equal to, or greater than the second base on alphanumeric order. + * */ @Override public int compare(Application o1, Application o2) { return o1.getInterviewSlot().getValue().compareTo(o2.getInterviewSlot().getValue()); diff --git a/src/main/java/seedu/address/logic/sort/NameComparator.java b/src/main/java/seedu/address/logic/sort/NameComparator.java index 48e6e2f6b20..4125e7bda2f 100644 --- a/src/main/java/seedu/address/logic/sort/NameComparator.java +++ b/src/main/java/seedu/address/logic/sort/NameComparator.java @@ -8,6 +8,10 @@ public class NameComparator implements Comparator { public static final String COMMAND_WORD = "name"; + /** + * Compares the two application's name field. Returns a negative integer, zero, or a positive integer as + * the first argument is less than, equal to, or greater than the second base on alphanumeric order. + * */ @Override public int compare(Application o1, Application o2) { return o1.getName().toString().compareTo(o2.getName().toString()); diff --git a/src/main/java/seedu/address/logic/sort/PriorityComparator.java b/src/main/java/seedu/address/logic/sort/PriorityComparator.java index 247707a4697..d8f4c59d0a9 100644 --- a/src/main/java/seedu/address/logic/sort/PriorityComparator.java +++ b/src/main/java/seedu/address/logic/sort/PriorityComparator.java @@ -14,6 +14,12 @@ public class PriorityComparator implements Comparator { private static final String PRIORITY_HIGH = "[" + PriorityTagType.HIGH + "]"; private static final String PRIORITY_LOW = "[" + PriorityTagType.LOW + "]"; + /** + * Compares the two application's priority field. Returns a negative integer, zero, or a positive integer as + * the first argument is less than, equal to, or greater than the second base on alphanumeric order. + * The default order from ascending to descend is as follows HIGH, MEDIUM, LOW. + * An empty tag will be considered as the lowest ranking, ranked below LOW. + * */ @Override public int compare(Application o1, Application o2) { Optional p1 = o1.getPriorityTag(); From e89f8635c2a9031e466b32f2d0f92fa526f6d981 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Wed, 30 Mar 2022 19:42:36 +0800 Subject: [PATCH 20/21] Update UserGuide.md Updated list feature to accommodate sorting parameters. --- docs/UserGuide.md | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 11145db8044..abe5e797cad 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -28,7 +28,7 @@ SoC InternApply (SIA) is a **desktop app for managing internship applications, o Some example commands you can try: * **`help`** : Shows a message explaining how to access the help page. - * **`list`** : Lists all applications. + * **`list`**`name desc` : Sort all applications base on company name in descending order. * **`reminder`** : Lists all applications with upcoming interviews within a week from now. @@ -108,11 +108,35 @@ Examples: * `add n/Shopee j/Software Engineer Intern p/87438807 e/hr@shopee.sg a/5 Science Park Dr, #06-40 t/SoftwareEngineering ` * `add n/Shopee j/Software Engineer Intern p/87438807 e/hr@shopee.sg a/5 Science Park Dr, #06-40 t/SoftwareEngineering pt/HIGH ast/NOT_APPLIED` -### Listing all applications : `list` +### Listing all applications in a sorted manner : `list` -Shows a list of all applications in SoC InternApply. +Sorts the list of all application in SoC InternApply base on the provided paramters. -Format: `list` +Format: `list [sorting paramter] [order by]` + +Sorting paramters: +- `name` : Sort by name of the company in alphabetical order starting with A in ascending order. +- `interview` : Sort by interview date of applications starting with the latest earliest date. +- `piroity` : Sort by piroity in the following order - HIGH, MEDIUM, LOW. +- `status` : Sort by status in the following order - ACCEPTED, REJECTED, INTERVIEWED, APPLIE and NOT_APPLIED. + +* If optional fields (i.e. interview date and time, piroirty, status) do not exist in that certain application, that application will be move to the bottom of the sorting order. If there is more than one of such application, it will be sorted alphabeticaly. + +Order by: +- `asc` : Order by ascending. +- `desc` : Order by descending (reverse order of ascending). + +Examples: +* `list interview desc` +* `list name desc`, running this will output: +``` +Sorted applications by name order by desc. +``` +> 💡 The `list` command also works without paramters. It will reverted to the last sorted paramter and order used by the user. This is used after using the `find` feature to list out all applications. + +> ⚠️ Applications are originally sorted in a chonological order base on create date and time. Do take note that after using the `list` feature to sort, you will not be able to sort the applications in chronological order. + +> ❗ Sorting will not apply to newly added or newly edited applications. Please re-run the `list` coomand with the respective paramters to sort as per you like. ### Listing applications with upcoming interviews: `reminder` @@ -194,8 +218,6 @@ Format: `exit` InternApply data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. -_More features coming soon ..._ - -------------------------------------------------------------------------------------------------------------------- ## FAQ From 87324a2a520c72fbdb07a36bc06c3c663820eac9 Mon Sep 17 00:00:00 2001 From: Zheng Teck Date: Wed, 30 Mar 2022 19:44:14 +0800 Subject: [PATCH 21/21] Update UserGuide.md Update list command in summary --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index abe5e797cad..a813776a58e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -234,8 +234,8 @@ InternApply data are saved in the hard disk automatically after any command that Action | Format, Examples --------|------------------ -**Help** | `help` -**List** | `list` +**Help** | `help`
`list interview desc` +**List** | `list [sorting paramter] [order by]` **Reminder**| `reminder` **Add** | `add n/NAME_OF_COMPANY p/PHONE_NUMBER a/ADDRESS j/JOB_TITLE e/EMAIL [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]`
e.g., `add n/Singtel j/UIUX Intern p/62527525 e/singtel@sg.com a/Singtel Group Strategic Communications and Brand, 31 Exeter Road, Comcentre #19-00 ast/APPLIED` **Edit** | `edit INDEX [n/NAME] [j/JOB_TITLE] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [idt/INTERVIEW_DATE_TIME] [t/TAG]... [pt/PRIORITY_TAG] [ast/APPLICATION_STATUS_TAG]`
e.g, `edit 1 n/Grab SG p/65358292 idt/17-03-2022 13:30`