diff --git a/src/main/java/tuteez/logic/Messages.java b/src/main/java/tuteez/logic/Messages.java index 2a8a100a4c9..26c3a9b15be 100644 --- a/src/main/java/tuteez/logic/Messages.java +++ b/src/main/java/tuteez/logic/Messages.java @@ -47,7 +47,7 @@ public static String format(Person person) { .append("; Address: ") .append(person.getAddress()) .append("; Telegram: ") - .append(person.getTelegramUsername()) + .append(person.getTelegramUsername().toString()) .append("; Tags: "); person.getTags().forEach(builder::append); builder.append("; Lessons: "); diff --git a/src/main/java/tuteez/logic/commands/AddCommand.java b/src/main/java/tuteez/logic/commands/AddCommand.java index fa963c172d9..b9ea2f7924d 100644 --- a/src/main/java/tuteez/logic/commands/AddCommand.java +++ b/src/main/java/tuteez/logic/commands/AddCommand.java @@ -32,7 +32,7 @@ public class AddCommand extends Command { + PREFIX_EMAIL + "EMAIL " + PREFIX_ADDRESS + "ADDRESS " + PREFIX_TELEGRAM + "TELEGRAM USERNAME" - + "[" + PREFIX_TAG + "TAG]...\n" + + " [" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "John Doe " + PREFIX_PHONE + "98765432 " diff --git a/src/main/java/tuteez/logic/parser/AddCommandParser.java b/src/main/java/tuteez/logic/parser/AddCommandParser.java index a9b7bb14a13..b9b45d1845e 100644 --- a/src/main/java/tuteez/logic/parser/AddCommandParser.java +++ b/src/main/java/tuteez/logic/parser/AddCommandParser.java @@ -38,7 +38,7 @@ public AddCommand parse(String args) throws ParseException { ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TELEGRAM, PREFIX_TAG, PREFIX_LESSON); - if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_PHONE) || !argMultimap.getPreamble().isEmpty()) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } @@ -47,8 +47,8 @@ public AddCommand parse(String args) throws ParseException { PREFIX_TELEGRAM); Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); - Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); - Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); + Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).orElse(null)); + Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).orElse(null)); TelegramUsername telegramUsername = ParserUtil.parseTelegramUsername( argMultimap.getValue(PREFIX_TELEGRAM).orElse(null)); diff --git a/src/main/java/tuteez/logic/parser/EditCommandParser.java b/src/main/java/tuteez/logic/parser/EditCommandParser.java index e785e948849..4c202629eb9 100644 --- a/src/main/java/tuteez/logic/parser/EditCommandParser.java +++ b/src/main/java/tuteez/logic/parser/EditCommandParser.java @@ -19,6 +19,9 @@ import tuteez.logic.commands.EditCommand; import tuteez.logic.commands.EditCommand.EditPersonDescriptor; import tuteez.logic.parser.exceptions.ParseException; +import tuteez.model.person.Address; +import tuteez.model.person.Email; +import tuteez.model.person.TelegramUsername; import tuteez.model.person.lesson.Lesson; import tuteez.model.tag.Tag; @@ -58,14 +61,16 @@ public EditCommand parse(String args) throws ParseException { editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get())); } if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) { - editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get())); + String email = argMultimap.getValue(PREFIX_EMAIL).get(); + setEditedEmail(editPersonDescriptor, email); } if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) { - editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get())); + String address = argMultimap.getValue(PREFIX_ADDRESS).get(); + setEditedAddress(editPersonDescriptor, address); } if (argMultimap.getValue(PREFIX_TELEGRAM).isPresent()) { - editPersonDescriptor.setTelegramUsername(ParserUtil.parseTelegramUsername( - argMultimap.getValue(PREFIX_TELEGRAM).get())); + String telegramUsername = argMultimap.getValue(PREFIX_TELEGRAM).get(); + setEditedTelegramUsername(editPersonDescriptor, telegramUsername); } parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); parseLessonsForEdit(argMultimap.getAllValues(PREFIX_LESSON)).ifPresent(editPersonDescriptor::setLessons); @@ -77,6 +82,31 @@ public EditCommand parse(String args) throws ParseException { return new EditCommand(index, editPersonDescriptor); } + private void setEditedEmail(EditPersonDescriptor editPersonDescriptor, String email) throws ParseException { + if (email.isEmpty()) { + editPersonDescriptor.setEmail(new Email(null)); + } else { + editPersonDescriptor.setEmail(ParserUtil.parseEmail(email)); + } + } + + private void setEditedAddress(EditPersonDescriptor editPersonDescriptor, String address) throws ParseException { + if (address.isEmpty()) { + editPersonDescriptor.setAddress(new Address(null)); + } else { + editPersonDescriptor.setAddress(ParserUtil.parseAddress(address)); + } + } + + private void setEditedTelegramUsername(EditPersonDescriptor editPersonDescriptor, String telegramUsername) + throws ParseException { + if (telegramUsername.isEmpty()) { + editPersonDescriptor.setTelegramUsername(TelegramUsername.empty()); + } else { + editPersonDescriptor.setTelegramUsername(ParserUtil.parseTelegramUsername(telegramUsername)); + } + } + /** * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty. * If {@code tags} contain only one element which is an empty string, it will be parsed into a diff --git a/src/main/java/tuteez/logic/parser/ParserUtil.java b/src/main/java/tuteez/logic/parser/ParserUtil.java index 4990dd9be13..54d0905b54e 100644 --- a/src/main/java/tuteez/logic/parser/ParserUtil.java +++ b/src/main/java/tuteez/logic/parser/ParserUtil.java @@ -74,7 +74,9 @@ public static Phone parsePhone(String phone) throws ParseException { * @throws ParseException if the given {@code address} is invalid. */ public static Address parseAddress(String address) throws ParseException { - requireNonNull(address); + if (address == null) { + return new Address(address); + } String trimmedAddress = address.trim(); if (!Address.isValidAddress(trimmedAddress)) { throw new ParseException(Address.MESSAGE_CONSTRAINTS); @@ -89,7 +91,9 @@ public static Address parseAddress(String address) throws ParseException { * @throws ParseException if the given {@code email} is invalid. */ public static Email parseEmail(String email) throws ParseException { - requireNonNull(email); + if (email == null) { + return new Email(email); + } String trimmedEmail = email.trim(); if (!Email.isValidEmail(trimmedEmail)) { throw new ParseException(Email.MESSAGE_CONSTRAINTS); @@ -136,12 +140,14 @@ public static TelegramUsername parseTelegramUsername(String username) throws Par return TelegramUsername.empty(); } String trimmedUsername = username.trim(); + if (!TelegramUsername.isValidTelegramHandle(trimmedUsername)) { throw new ParseException(TelegramUsername.MESSAGE_CONSTRAINTS); } return TelegramUsername.of(trimmedUsername); } + /** * Parses a {@code String lesson} into a {@code Lesson}. * Leading and trailing whitespaces will be trimmed. diff --git a/src/main/java/tuteez/model/person/Address.java b/src/main/java/tuteez/model/person/Address.java index 01ff37471eb..f000adca695 100644 --- a/src/main/java/tuteez/model/person/Address.java +++ b/src/main/java/tuteez/model/person/Address.java @@ -9,7 +9,8 @@ */ public class Address { - public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank"; + public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank" + + ", unless when editing."; /* * The first character of the address must not be a whitespace, @@ -25,8 +26,11 @@ public class Address { * @param address A valid address. */ public Address(String address) { - requireNonNull(address); - checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS); + // address argument can be null to make it optional + if (address != null) { + requireNonNull(address); + checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS); + } value = address; } @@ -34,11 +38,17 @@ public Address(String address) { * Returns true if a given string is a valid email. */ public static boolean isValidAddress(String test) { + if (test == null) { + return true; + } return test.matches(VALIDATION_REGEX); } @Override public String toString() { + if (value == null) { + return ""; + } return value; } @@ -54,12 +64,15 @@ public boolean equals(Object other) { } Address otherAddress = (Address) other; + if (value == null) { + return otherAddress.value == null; + } return value.equals(otherAddress.value); } @Override public int hashCode() { - return value.hashCode(); + return value == null ? 0 : value.hashCode(); } } diff --git a/src/main/java/tuteez/model/person/Email.java b/src/main/java/tuteez/model/person/Email.java index a239d260dbe..7925e83e961 100644 --- a/src/main/java/tuteez/model/person/Email.java +++ b/src/main/java/tuteez/model/person/Email.java @@ -10,7 +10,7 @@ public class Email { private static final String SPECIAL_CHARACTERS = "+_.-"; - public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain " + public static final String MESSAGE_CONSTRAINTS = "If provided, Emails should be of the format local-part@domain " + "and adhere to the following constraints:\n" + "1. The local-part should only contain alphanumeric characters and these special characters, excluding " + "the parentheses, (" + SPECIAL_CHARACTERS + "). The local-part may not start or end with any special " @@ -39,8 +39,11 @@ public class Email { * @param email A valid email address. */ public Email(String email) { - requireNonNull(email); - checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS); + // email argument can be null to make it optional + if (email != null) { + requireNonNull(email); + checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS); + } value = email; } @@ -48,11 +51,17 @@ public Email(String email) { * Returns if a given string is a valid email. */ public static boolean isValidEmail(String test) { + if (test == null) { + return true; + } return test.matches(VALIDATION_REGEX); } @Override public String toString() { + if (value == null) { + return ""; + } return value; } @@ -68,12 +77,15 @@ public boolean equals(Object other) { } Email otherEmail = (Email) other; + if (value == null) { + return otherEmail.value == null; + } return value.equals(otherEmail.value); } @Override public int hashCode() { - return value.hashCode(); + return value == null ? 0 : value.hashCode(); } } diff --git a/src/main/java/tuteez/model/person/TelegramUsername.java b/src/main/java/tuteez/model/person/TelegramUsername.java index fd382756179..71933642d1f 100644 --- a/src/main/java/tuteez/model/person/TelegramUsername.java +++ b/src/main/java/tuteez/model/person/TelegramUsername.java @@ -14,7 +14,7 @@ public class TelegramUsername { public static final String MESSAGE_CONSTRAINTS = "Telegram usernames must be at least 5 characters long, and can only contain a-z/A-Z, 0-9, and underscores." + " Telegram usernames are case insensitive, and will be in lowercase. It must start with a letter," - + " and should not be blank."; + + " and should not be blank unless the user is editing."; public static final String VALIDATION_REGEX = "^[a-zA-Z][a-zA-Z0-9_]{4,31}$"; diff --git a/src/main/java/tuteez/storage/JsonAdaptedPerson.java b/src/main/java/tuteez/storage/JsonAdaptedPerson.java index 29e25cecbba..51b62d13e8a 100644 --- a/src/main/java/tuteez/storage/JsonAdaptedPerson.java +++ b/src/main/java/tuteez/storage/JsonAdaptedPerson.java @@ -126,9 +126,6 @@ private Phone getModelPhone(String phone) throws IllegalValueException { } private Email getModelEmail(String email) throws IllegalValueException { - if (email == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName())); - } if (!Email.isValidEmail(email)) { throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS); } @@ -136,9 +133,6 @@ private Email getModelEmail(String email) throws IllegalValueException { } private Address getModelAddress(String address) throws IllegalValueException { - if (address == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName())); - } if (!Address.isValidAddress(address)) { throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS); } diff --git a/src/main/java/tuteez/ui/PersonCard.java b/src/main/java/tuteez/ui/PersonCard.java index 278d29d68f7..5235b68db67 100644 --- a/src/main/java/tuteez/ui/PersonCard.java +++ b/src/main/java/tuteez/ui/PersonCard.java @@ -12,7 +12,7 @@ import tuteez.model.person.TelegramUsername; /** - * An UI component that displays information of a {@code Person}. + * A UI component that displays information of a {@code Person}. */ public class PersonCard extends UiPart { @@ -59,8 +59,8 @@ public PersonCard(Person person, int displayedIndex) { name.setText(person.getName().fullName); phone.setText(person.getPhone().value); setTelegramUsernameText(person); - address.setText(person.getAddress().value); - email.setText(person.getEmail().value); + setAddressText(person); + setEmailText(person); person.getTags().stream() .sorted(Comparator.comparing(tag -> tag.tagName)) .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); @@ -72,6 +72,24 @@ public PersonCard(Person person, int displayedIndex) { .forEach(lesson -> lessons.getChildren().add(new Label(lesson.getDayAndTime()))); } + private void setAddressText(Person person) { + if (person.getAddress().value != null) { + address.setText(person.getAddress().value); + address.setVisible(true); + } else { + address.setVisible(false); + } + } + + private void setEmailText(Person person) { + if (person.getEmail().value != null) { + email.setText(person.getEmail().value); + email.setVisible(true); + } else { + email.setVisible(false); + } + } + private void setTelegramUsernameText(Person person) { TelegramUsername username = person.getTelegramUsername(); if (username != null && username.telegramUsername != null && !username.telegramUsername.isEmpty()) { diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index 8d531c6dd4c..ff78bc41fbb 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -31,8 +31,8 @@