diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3c6b1e23021..8743941e6df 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -80,7 +80,7 @@ Format: `help` Adds a contact to the address book. -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS g/GITHUB_USERNAME [t/TAG] [ts/TECH_STACK]…​` +Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS g/GITHUB_USERNAME [t/TAG] pp/PROFILE_PICTURE [ts/TECH_STACK]…​` @@ -89,8 +89,8 @@ Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS g/GITHUB_USERNAME [t/TAG] [ Examples: -- `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 g/johnDoee` -- `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 g/betBetty t/criminal ts/Flutter` +- `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 g/johnDoee pp/https://api-prod-minimal-v510.vercel.app/assets/images/avatar/avatar_1.jpg` +- `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 g/betBetty t/criminal ts/Flutter pp/https://api-prod-minimal-v510.vercel.app/assets/images/avatar/avatar_1.jpg` #### Listing all contacts : `list` @@ -102,7 +102,7 @@ Format: `list` Edits an existing contact in the address book. -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [g/GITHUB_USERNAME] [t/TAG]…​ [ts/TECH_STACK]…​` +Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [g/GITHUB_USERNAME] [pp/PROFILE_PICTURE] [t/TAG]…​ [ts/TECH_STACK]…​` - Edits the contact at the specified `INDEX`. The index refers to the index number shown in the displayed contact list. The index **must be a positive integer** 1, 2, 3, …​ - At least one of the optional fields must be provided. @@ -245,14 +245,14 @@ _Details coming soon ..._ ## Command summary -| Action | Format, Examples | -|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS g/GITHUB_USERNAME [t/TAG] [ts/TECH_STACK]…​`
e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 g/Jamesho123 t/friend t/colleague ts/Java ts/C++` | -| **Clear** | `clear` | -| **Delete** | `delete INDEX`
e.g., `delete 3` | -| **Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [g/GITHUB_USERNAME] [t/TAG]…​ [ts/TECH_STACK]…​ `
e.g.,`edit 2 n/James Lee e/jameslee@example.com` | -| **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` | -| **Find by Tags** | `find-tags KEYWORD [MORE_KEYWORDS]`
e.g., `find-tags School Work` | -| **Find Tech Stack** | `find-ts KEYWORD [MORE_KEYWORDS]`
e.g., `find-ts Java Python` | -| **List** | `list` | -| **Help** | `help` | +| Action | Format, Examples | +|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS g/GITHUB_USERNAME pp/PROFILE_PICTURE [t/TAG] [ts/TECH_STACK]…​`
e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 g/Jamesho123 pp/https://api-prod-minimal-v510.vercel.app/assets/images/avatar/avatar_1.jpg t/friend t/colleague ts/Java ts/C++` | +| **Clear** | `clear` | +| **Delete** | `delete INDEX`
e.g., `delete 3` | +| **Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [g/GITHUB_USERNAME] [pp/PROFILE_PICTURE] [t/TAG]…​ [ts/TECH_STACK]…​ `
e.g.,`edit 2 n/James Lee e/jameslee@example.com` | +| **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` | +| **Find by Tags** | `find-tags KEYWORD [MORE_KEYWORDS]`
e.g., `find-tags School Work` | +| **Find Tech Stack** | `find-ts KEYWORD [MORE_KEYWORDS]`
e.g., `find-ts Java Python` | +| **List** | `list` | +| **Help** | `help` | diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index a10f1abf839..e4361aa2da6 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -168,6 +168,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { return initializedPrefs; } + @Override public void start(Stage primaryStage) { logger.info("Starting CodeConnect " + MainApp.VERSION); diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index 65894c75bec..9f37b138bb4 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -45,6 +45,8 @@ public static String format(Contact contact) { .append(contact.getAddress()) .append("; GitHub Username: ") .append(contact.getGitHubUsername()) + .append("; Profile Picture: ") + .append(contact.getProfilePicture()) .append("; Tech Stack: "); contact.getTechStack().forEach(builder::append); builder.append("; Tags: "); diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index 1b7c67cae50..157a96f6738 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -1,19 +1,21 @@ package seedu.address.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_GITHUB_USERNAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_TECH_STACK; +import static seedu.address.logic.parser.CliSyntax.PREFIX_GITHUB_USERNAME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PROFILE_PICTURE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.Messages; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; import seedu.address.model.contact.Contact; +import seedu.address.model.contact.ProfilePicture; /** * Adds a contact to the address book. @@ -28,7 +30,8 @@ public class AddCommand extends Command { + PREFIX_PHONE + "PHONE " + PREFIX_EMAIL + "EMAIL " + PREFIX_ADDRESS + "ADDRESS " - + PREFIX_GITHUB_USERNAME + "GITHUB USERNAME " + + PREFIX_GITHUB_USERNAME + "GITHUB_USERNAME " + + PREFIX_PROFILE_PICTURE + "PROFILE_PICTURE " + "[" + PREFIX_TECH_STACK + "TECH STACK]...\n" + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " @@ -37,6 +40,7 @@ public class AddCommand extends Command { + PREFIX_EMAIL + "johnd@example.com " + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " + PREFIX_GITHUB_USERNAME + "johndoee123 " + + PREFIX_PROFILE_PICTURE + ProfilePicture.DEFAULT_URL + PREFIX_TECH_STACK + "Java " + PREFIX_TECH_STACK + "Python " + PREFIX_TAG + "friends " diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index e08f4d62a56..b2f52843d35 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -8,6 +8,7 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import static seedu.address.logic.parser.CliSyntax.PREFIX_TECH_STACK; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PROFILE_PICTURE; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_CONTACTS; import java.util.Collections; @@ -31,6 +32,7 @@ import seedu.address.model.contact.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.techstack.TechStack; +import seedu.address.model.contact.ProfilePicture; /** * Edits the details of an existing contact in the address book. @@ -48,6 +50,7 @@ public class EditCommand extends Command { + "[" + PREFIX_EMAIL + "EMAIL] " + "[" + PREFIX_ADDRESS + "ADDRESS] " + "[" + PREFIX_GITHUB_USERNAME + "GITHUB USERNAME]" + + "[" + PREFIX_PROFILE_PICTURE + "PROFILE_PICTURE]" + "[" + PREFIX_TECH_STACK + "TECH_STACK...\n" + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " 1 " @@ -110,9 +113,10 @@ private static Contact createEditedContact(Contact contactToEdit, EditContactDes editContactDescriptor.getGitHubUsername().orElse(contactToEdit.getGitHubUsername()); Set updatedTechStack = editContactDescriptor.getTechStack().orElse(contactToEdit.getTechStack()); Set updatedTags = editContactDescriptor.getTags().orElse(contactToEdit.getTags()); + ProfilePicture updatedProfilePicture = editContactDescriptor.getProfilePicture().orElse(contactToEdit.getProfilePicture()); return new Contact(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedGitHubUsername, - updatedTechStack, updatedTags); + updatedTechStack, updatedTags, updatedProfilePicture); } @Override @@ -152,7 +156,8 @@ public static class EditContactDescriptor { private Set techStack; private Set tags; - public EditContactDescriptor() {} + private ProfilePicture profilePicture; + /** * Copy constructor. @@ -166,14 +171,17 @@ public EditContactDescriptor(EditContactDescriptor toCopy) { setGitHubUsername(toCopy.gitHubUsername); setTechStack(toCopy.techStack); setTags(toCopy.tags); + setProfilePicture(toCopy.profilePicture); } + public EditContactDescriptor() {} + /** * Returns true if at least one field is edited. */ public boolean isAnyFieldEdited() { return CollectionUtil.isAnyNonNull(name, phone, email, address, - gitHubUsername, techStack, tags); + gitHubUsername, techStack, tags, profilePicture); } public void setName(Name name) { @@ -215,6 +223,14 @@ public Optional getGitHubUsername() { return Optional.ofNullable(gitHubUsername); } + public void setProfilePicture(ProfilePicture profilePicture) { + this.profilePicture = profilePicture; + } + + public Optional getProfilePicture() { + return Optional.ofNullable(this.profilePicture); + } + /** * Sets {@code techStack} to this object's {@code techStack}. * A defensive copy of {@code techStack} is used internally. @@ -267,7 +283,8 @@ public boolean equals(Object other) { && Objects.equals(address, otherEditContactDescriptor.address) && Objects.equals(gitHubUsername, otherEditContactDescriptor.gitHubUsername) && Objects.equals(techStack, otherEditContactDescriptor.techStack) - && Objects.equals(tags, otherEditContactDescriptor.tags); + && Objects.equals(tags, otherEditContactDescriptor.tags) + && Objects.equals(profilePicture, otherEditContactDescriptor.profilePicture); } @Override diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 61ed1262c3d..b71f0c57ea0 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -8,6 +8,8 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import static seedu.address.logic.parser.CliSyntax.PREFIX_TECH_STACK; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PROFILE_PICTURE; + import java.util.Set; import java.util.stream.Stream; @@ -20,6 +22,7 @@ import seedu.address.model.contact.Name; import seedu.address.model.contact.Contact; import seedu.address.model.contact.Phone; +import seedu.address.model.contact.ProfilePicture; import seedu.address.model.tag.Tag; import seedu.address.model.techstack.TechStack; @@ -36,7 +39,7 @@ public class AddCommandParser implements Parser { public AddCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, - PREFIX_GITHUB_USERNAME, PREFIX_TECH_STACK, PREFIX_TAG); + PREFIX_GITHUB_USERNAME, PREFIX_PROFILE_PICTURE, PREFIX_TECH_STACK, PREFIX_TAG); if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_GITHUB_USERNAME, PREFIX_PHONE, PREFIX_EMAIL) @@ -45,7 +48,7 @@ public AddCommand parse(String args) throws ParseException { } argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, - PREFIX_GITHUB_USERNAME); + PREFIX_GITHUB_USERNAME, PREFIX_PROFILE_PICTURE); 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()); @@ -54,8 +57,9 @@ public AddCommand parse(String args) throws ParseException { Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); Set techStackList = ParserUtil.parseTechStacks(argMultimap.getAllValues(PREFIX_TECH_STACK)); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + ProfilePicture profilePicture = ParserUtil.parseProfilePicture(argMultimap.getValue(PREFIX_PROFILE_PICTURE).orElse("")); - Contact contact = new Contact(name, phone, email, address, gitHubUsername, techStackList, tagList); + Contact contact = new Contact(name, phone, email, address, gitHubUsername, techStackList, tagList, profilePicture); return new AddCommand(contact); } diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 55ab48255e2..ff6c3f75a96 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -13,5 +13,6 @@ public class CliSyntax { public static final Prefix PREFIX_GITHUB_USERNAME = new Prefix("g/"); public static final Prefix PREFIX_TECH_STACK = new Prefix("ts/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); + public static final Prefix PREFIX_PROFILE_PICTURE = new Prefix("pp/"); } diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java index f29683d4d7d..3756e52b524 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -3,12 +3,13 @@ import static java.util.Objects.requireNonNull; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_GITHUB_USERNAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PROFILE_PICTURE; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_GITHUB_USERNAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import static seedu.address.logic.parser.CliSyntax.PREFIX_TECH_STACK; +import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; import java.util.Collection; import java.util.Collections; @@ -36,7 +37,7 @@ public EditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, - PREFIX_GITHUB_USERNAME, PREFIX_TECH_STACK, PREFIX_TAG); + PREFIX_GITHUB_USERNAME, PREFIX_PROFILE_PICTURE, PREFIX_TECH_STACK, PREFIX_TAG); Index index; @@ -47,7 +48,7 @@ public EditCommand parse(String args) throws ParseException { } argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, - PREFIX_GITHUB_USERNAME); + PREFIX_GITHUB_USERNAME, PREFIX_PROFILE_PICTURE); EditContactDescriptor editContactDescriptor = new EditContactDescriptor(); @@ -67,6 +68,10 @@ public EditCommand parse(String args) throws ParseException { editContactDescriptor.setGitHubUsername( ParserUtil.parseGitHubUsername(argMultimap.getValue(PREFIX_GITHUB_USERNAME).get())); } + if (argMultimap.getValue(PREFIX_PROFILE_PICTURE).isPresent()) { + editContactDescriptor.setProfilePicture(ParserUtil.parseProfilePicture(argMultimap. + getValue(PREFIX_PROFILE_PICTURE).get())); + } parseTechStackForEdit(argMultimap.getAllValues(PREFIX_TECH_STACK)) .ifPresent(editContactDescriptor::setTechStack); parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editContactDescriptor::setTags); diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index e1c73bbee0b..6686858c4b1 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -14,6 +14,7 @@ import seedu.address.model.contact.GitHubUsername; import seedu.address.model.contact.Name; import seedu.address.model.contact.Phone; +import seedu.address.model.contact.ProfilePicture; import seedu.address.model.tag.Tag; import seedu.address.model.techstack.TechStack; @@ -82,6 +83,16 @@ public static Address parseAddress(String address) throws ParseException { return new Address(trimmedAddress); } + /** + * Parses a {@code String profilePictureURL} into an {@code ProfilePicture}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code address} is invalid. + */ + public static ProfilePicture parseProfilePicture(String profilePictureURLArgument) { + return new ProfilePicture(profilePictureURLArgument); + } + /** * Parses a {@code String address} into an {@code Address}. * Leading and trailing whitespaces will be trimmed. diff --git a/src/main/java/seedu/address/model/contact/Contact.java b/src/main/java/seedu/address/model/contact/Contact.java index feaa1915a1f..d47c0eb5ee0 100644 --- a/src/main/java/seedu/address/model/contact/Contact.java +++ b/src/main/java/seedu/address/model/contact/Contact.java @@ -9,6 +9,7 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.tag.Tag; + import seedu.address.model.techstack.TechStack; /** @@ -28,13 +29,16 @@ public class Contact { private final Set techStack = new HashSet<>(); private final Set tags = new HashSet<>(); + private final ProfilePicture profilePicture; + /** * Every field must be present and not null. */ public Contact(Name name, Phone phone, Email email, Address address, GitHubUsername gitHubUsername, - Set techStack, Set tags) { - requireAllNonNull(name, phone, email, address, tags, gitHubUsername, techStack); + Set techStack, Set tags, ProfilePicture profilePicture) { + requireAllNonNull(name, phone, email, address, tags, gitHubUsername, techStack, profilePicture); this.name = name; + this.profilePicture = profilePicture; this.phone = phone; this.email = email; this.address = address; @@ -55,6 +59,10 @@ public Email getEmail() { return email; } + public ProfilePicture getProfilePicture() { + return profilePicture; + } + public Address getAddress() { return address; } @@ -112,6 +120,7 @@ public boolean equals(Object other) { && email.equals(otherContact.email) && address.equals(otherContact.address) && gitHubUsername.equals(otherContact.gitHubUsername) + && profilePicture.equals(otherContact.profilePicture) && techStack.equals(otherContact.techStack) && tags.equals(otherContact.tags); } @@ -130,6 +139,7 @@ public String toString() { .add("email", email) .add("address", address) .add("github_username", gitHubUsername) + .add("profile_picture", profilePicture) .add("tech_stack", techStack) .add("tags", tags) .toString(); diff --git a/src/main/java/seedu/address/model/contact/ProfilePicture.java b/src/main/java/seedu/address/model/contact/ProfilePicture.java new file mode 100644 index 00000000000..7c380931d9a --- /dev/null +++ b/src/main/java/seedu/address/model/contact/ProfilePicture.java @@ -0,0 +1,40 @@ +package seedu.address.model.contact; + +import java.util.Objects; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +public class ProfilePicture { + public final static String DEFAULT_URL = "https://api-prod-minimal-v510.vercel.app/assets/images/avatar/avatar_13.jpg"; + String url; + public ProfilePicture(String url) { + this.url = url; + } + + public String get() { + return this.url; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + // instanceof handles nulls + if (!(o instanceof ProfilePicture)) { + return false; + } ProfilePicture that = (ProfilePicture) o; + return Objects.equals(this.url, that.url); + } + + + + @Override + public int hashCode() { + return Objects.hash(url); + } + + @Override + public String toString() { + return url; + } +} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index d9f3eba9326..aae3cb6830b 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -14,6 +14,7 @@ import seedu.address.model.contact.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.techstack.TechStack; +import seedu.address.model.contact.ProfilePicture; /** @@ -24,22 +25,22 @@ public static Contact[] getSampleContacts() { return new Contact[] { new Contact(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), new Address("Blk 30 Geylang Street 29, #06-40"), new GitHubUsername("alexYeohhh"), - getTechStackSet("React"), getTagSet("friends")), + getTechStackSet("React"), getTagSet("friends"), new ProfilePicture("")), new Contact(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), new GitHubUsername("Berney-Yu"), - getTechStackSet("Docker"), getTagSet("colleagues", "friends")), + getTechStackSet("Docker"), getTagSet("colleagues", "friends"), new ProfilePicture("")), new Contact(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), new GitHubUsername("Charloove666"), - getTechStackSet("JavaScript", "C++"), getTagSet("neighbours")), + getTechStackSet("JavaScript", "C++"), getTagSet("neighbours"), new ProfilePicture("")), new Contact(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), new GitHubUsername("DavidLi987"), - getTechStackSet("C#"), getTagSet("family")), + getTechStackSet("C#"), getTagSet("family"), new ProfilePicture("")), new Contact(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), new Address("Blk 47 Tampines Street 20, #17-35"), new GitHubUsername("IrfyIb"), - getTechStackSet("SQL", "Django"), getTagSet("classmates")), + getTechStackSet("SQL", "Django"), getTagSet("classmates"), new ProfilePicture("")), new Contact(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), new Address("Blk 45 Aljunied Street 85, #11-31"), new GitHubUsername("BalaRoyy"), - getTechStackSet("Python"), getTagSet("colleagues")) + getTechStackSet("Python"), getTagSet("colleagues"), new ProfilePicture("")) }; } diff --git a/src/main/java/seedu/address/storage/JsonAdaptedContact.java b/src/main/java/seedu/address/storage/JsonAdaptedContact.java index 0687e4a5883..4397e54fc84 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedContact.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedContact.java @@ -18,7 +18,7 @@ import seedu.address.model.contact.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.techstack.TechStack; - +import seedu.address.model.contact.ProfilePicture; /** * Jackson-friendly version of {@link Contact}. */ @@ -31,9 +31,16 @@ class JsonAdaptedContact { private final String email; private final String address; private final String gitHubUsername; + private final String profilePicture; + private final List techStack = new ArrayList<>(); private final List tags = new ArrayList<>(); + + + final static String SAMPLE_PROFILE_PICTURE_URL = "https://static.vecteezy.com/system/resources/previews/019/766/19" + + "8/non_2x/apple-logo-apple-icon-transparent-free-png.png"; + /** * Constructs a {@code JsonAdaptedContact} with the given contact details. */ @@ -41,6 +48,7 @@ class JsonAdaptedContact { public JsonAdaptedContact(@JsonProperty("name") String name, @JsonProperty("phone") String phone, @JsonProperty("email") String email, @JsonProperty("address") String address, @JsonProperty ("github_username") String gitHubUsername, + @JsonProperty ("profile_picture") String profilePicture, @JsonProperty ("tech_stack") List techStack, @JsonProperty("tags") List tags) { this.name = name; @@ -48,6 +56,7 @@ public JsonAdaptedContact(@JsonProperty("name") String name, @JsonProperty("phon this.email = email; this.address = address; this.gitHubUsername = gitHubUsername; + this.profilePicture = profilePicture; if (techStack != null) { this.techStack.addAll(techStack); } @@ -65,6 +74,7 @@ public JsonAdaptedContact(Contact source) { email = source.getEmail().value; address = source.getAddress().value; gitHubUsername = source.getGitHubUsername().username; + profilePicture = source.getProfilePicture().get(); techStack.addAll(source.getTechStack().stream() .map(JsonAdaptedTechStack::new) .collect(Collectors.toList())); @@ -132,9 +142,10 @@ public Contact toModelType() throws IllegalValueException { final Set modelTechStack = new HashSet<>(personTechStack); final Set modelTags = new HashSet<>(personTags); + final ProfilePicture modelProfilePicture = new ProfilePicture(profilePicture); return new Contact(modelName, modelPhone, modelEmail, modelAddress, modelGitHubUsername, modelTechStack, - modelTags); + modelTags, modelProfilePicture); } } diff --git a/src/main/java/seedu/address/ui/ContactCard.java b/src/main/java/seedu/address/ui/ContactCard.java index ba173716402..9c412ac2bdb 100644 --- a/src/main/java/seedu/address/ui/ContactCard.java +++ b/src/main/java/seedu/address/ui/ContactCard.java @@ -4,10 +4,14 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + import javafx.scene.layout.HBox; import javafx.scene.layout.Region; import seedu.address.logic.MailApp; import seedu.address.model.contact.Contact; +import seedu.address.model.contact.ProfilePicture; /** * An UI component that displays information of a {@code Contact}. @@ -47,12 +51,24 @@ public class ContactCard extends UiPart { @FXML private HBox tags; + @FXML + private ImageView profilePicture; /** * Creates a {@code ContactCode} with the given {@code Contact} and index to display. */ public ContactCard(Contact contact, int displayedIndex) { super(FXML); this.contact = contact; + + try { + Image image = new Image(contact.getProfilePicture().get()); + profilePicture.setImage(image); + } catch (IllegalArgumentException e) { + // Handle invalid image URL + System.err.println("Invalid image URL: " + contact.getProfilePicture().get()); + profilePicture.setImage(new Image(ProfilePicture.DEFAULT_URL)); + } + id.setText(displayedIndex + ". "); name.setText(contact.getName().fullName); phone.setText("Phone: " + contact.getPhone().value); @@ -74,5 +90,7 @@ public ContactCard(Contact contact, int displayedIndex) { mailApp.handleEmailClicked(); }); } + + } diff --git a/src/main/resources/view/ContactListCard.fxml b/src/main/resources/view/ContactListCard.fxml index 07855cbd3e6..5d31d65b8bc 100644 --- a/src/main/resources/view/ContactListCard.fxml +++ b/src/main/resources/view/ContactListCard.fxml @@ -1,5 +1,4 @@ - @@ -7,28 +6,31 @@ + + - + + - + - + - + + + diff --git a/src/test/data/JsonSerializableCodeConnectTest/typicalContactCodeConnect.json b/src/test/data/JsonSerializableCodeConnectTest/typicalContactCodeConnect.json index 3936cbf6f45..daeabb6b375 100644 --- a/src/test/data/JsonSerializableCodeConnectTest/typicalContactCodeConnect.json +++ b/src/test/data/JsonSerializableCodeConnectTest/typicalContactCodeConnect.json @@ -6,6 +6,7 @@ "email" : "alice@example.com", "address" : "123, Jurong West Ave 6, #08-111", "github_username": "AliceInWonderland2", + "profile_picture": "", "tags" : [ "friends" ], "tech_stack" : [ "java" ] }, { @@ -14,6 +15,7 @@ "email" : "johnd@example.com", "address" : "311, Clementi Ave 2, #02-25", "github_username": "BenSon0", + "profile_picture": "", "tags" : [ "owesMoney", "friends" ], "tech_stack" : [ "java", "python" ] }, { @@ -22,6 +24,7 @@ "email" : "heinz@example.com", "address" : "wall street", "github_username": "CarlKurzCK", + "profile_picture": "", "tags" : [ ] }, { "name" : "Daniel Meier", @@ -29,12 +32,14 @@ "email" : "cornelia@example.com", "address" : "10th street", "github_username": "Meier200", + "profile_picture": "", "tags" : [ "friends" ], "tech_stack" : [ "java" ] }, { "name" : "Elle Meyer", "phone" : "9482224", "email" : "werner@example.com", + "profile_picture": "", "address" : "michegan ave", "github_username": "Ellieellie", "tags" : [ ] @@ -44,6 +49,7 @@ "email" : "lydia@example.com", "address" : "little tokyo", "github_username": "FifiKunz", + "profile_picture": "", "tags" : [ ] }, { "name" : "George Best", @@ -51,6 +57,7 @@ "email" : "anna@example.com", "address" : "4th street", "github_username": "GeBest2103", + "profile_picture": "", "tags" : [ ] } ] } diff --git a/src/test/java/seedu/address/model/contact/ProfilePictureTest.java b/src/test/java/seedu/address/model/contact/ProfilePictureTest.java new file mode 100644 index 00000000000..f1632023a13 --- /dev/null +++ b/src/test/java/seedu/address/model/contact/ProfilePictureTest.java @@ -0,0 +1,31 @@ +package seedu.address.model.contact; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ProfilePictureTest { + + @Test + public void constructor_validUrl_success() { + String validUrl = "https://example.com/image.jpg"; + ProfilePicture profilePicture = new ProfilePicture(validUrl); + assertEquals(validUrl, profilePicture.get()); + } + + + @Test + public void equals_sameUrl_returnsTrue() { + String url = "https://example.com/image.jpg"; + ProfilePicture profilePicture1 = new ProfilePicture(url); + ProfilePicture profilePicture2 = new ProfilePicture(url); + assertEquals(profilePicture1, profilePicture2); + } + + @Test + public void equals_differentUrls_returnsFalse() { + ProfilePicture profilePicture1 = new ProfilePicture("https://example.com/image1.jpg"); + ProfilePicture profilePicture2 = new ProfilePicture("https://example.com/image2.jpg"); + assertEquals(false, profilePicture1.equals(profilePicture2)); + } +} diff --git a/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java b/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java index 0d8ae677ff3..f19b998acb0 100644 --- a/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java +++ b/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java @@ -32,6 +32,7 @@ public class JsonAdaptedContactTest { private static final String VALID_EMAIL = BENSON.getEmail().toString(); private static final String VALID_ADDRESS = BENSON.getAddress().toString(); private static final String VALID_GITHUB_USERNAME = BENSON.getGitHubUsername().toString(); + private static final String VALID_PROFILE_PICTURE = BENSON.getProfilePicture().get(); private static final List VALID_TECH_STACK = BENSON.getTechStack().stream() .map(JsonAdaptedTechStack::new) .collect(Collectors.toList()); @@ -48,7 +49,7 @@ public void toModelType_validContactDetails_returnsContact() throws Exception { @Test public void toModelType_invalidName_throwsIllegalValueException() { JsonAdaptedContact contact = - new JsonAdaptedContact(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_GITHUB_USERNAME, + new JsonAdaptedContact(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = Name.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); @@ -57,7 +58,7 @@ public void toModelType_invalidName_throwsIllegalValueException() { @Test public void toModelType_nullName_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -66,7 +67,7 @@ public void toModelType_nullName_throwsIllegalValueException() { public void toModelType_invalidPhone_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = Phone.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -74,7 +75,7 @@ public void toModelType_invalidPhone_throwsIllegalValueException() { @Test public void toModelType_nullPhone_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -83,7 +84,7 @@ public void toModelType_nullPhone_throwsIllegalValueException() { public void toModelType_invalidEmail_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = Email.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -91,7 +92,7 @@ public void toModelType_invalidEmail_throwsIllegalValueException() { @Test public void toModelType_nullEmail_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -100,7 +101,7 @@ public void toModelType_nullEmail_throwsIllegalValueException() { public void toModelType_invalidAddress_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = Address.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -108,7 +109,7 @@ public void toModelType_invalidAddress_throwsIllegalValueException() { @Test public void toModelType_nullAddress_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -116,7 +117,7 @@ public void toModelType_nullAddress_throwsIllegalValueException() { public void toModelType_invalidGitHubUsername_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, - INVALID_GITHUB_USERNAME, VALID_TECH_STACK, VALID_TAGS); + INVALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = GitHubUsername.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -124,7 +125,7 @@ public void toModelType_invalidGitHubUsername_throwsIllegalValueException() { @Test public void toModelType_nullGitHubUsername_throwsIllegalValueException() { JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, - null, VALID_TECH_STACK, VALID_TAGS); + null, VALID_PROFILE_PICTURE, VALID_TECH_STACK, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, GitHubUsername.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, contact::toModelType); } @@ -135,7 +136,7 @@ public void toModelType_invalidTags_throwsIllegalValueException() { invalidTags.add(new JsonAdaptedTag(INVALID_TAG)); JsonAdaptedContact contact = new JsonAdaptedContact(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, - VALID_GITHUB_USERNAME, VALID_TECH_STACK, invalidTags); + VALID_GITHUB_USERNAME, VALID_PROFILE_PICTURE, VALID_TECH_STACK, invalidTags); assertThrows(IllegalValueException.class, contact::toModelType); } diff --git a/src/test/java/seedu/address/testutil/ContactBuilder.java b/src/test/java/seedu/address/testutil/ContactBuilder.java index 42b928310b5..33fa354f027 100644 --- a/src/test/java/seedu/address/testutil/ContactBuilder.java +++ b/src/test/java/seedu/address/testutil/ContactBuilder.java @@ -3,12 +3,16 @@ import java.util.HashSet; import java.util.Set; -import seedu.address.model.contact.Address; -import seedu.address.model.contact.Contact; -import seedu.address.model.contact.Email; -import seedu.address.model.contact.GitHubUsername; import seedu.address.model.contact.Name; +import seedu.address.model.contact.ProfilePicture; +import seedu.address.model.contact.GitHubUsername; import seedu.address.model.contact.Phone; +import seedu.address.model.contact.Email; +import seedu.address.model.contact.Address; +import seedu.address.model.contact.Contact; + + + import seedu.address.model.tag.Tag; import seedu.address.model.techstack.TechStack; import seedu.address.model.util.SampleDataUtil; @@ -31,6 +35,7 @@ public class ContactBuilder { private GitHubUsername gitHubUsername; private Set techStack; private Set tags; + private ProfilePicture profilePicture; /** * Creates a {@code ContactBuilder} with the default details. @@ -43,6 +48,7 @@ public ContactBuilder() { gitHubUsername = new GitHubUsername(DEFAULT_GITHUB_USERNAME); techStack = new HashSet<>(); tags = new HashSet<>(); + profilePicture = new ProfilePicture(""); } /** @@ -56,6 +62,7 @@ public ContactBuilder(Contact contactToCopy) { gitHubUsername = contactToCopy.getGitHubUsername(); techStack = new HashSet<>(contactToCopy.getTechStack()); tags = new HashSet<>(contactToCopy.getTags()); + profilePicture = new ProfilePicture(""); } /** @@ -114,8 +121,13 @@ public ContactBuilder withGitHubUsername(String gitHubUsername) { return this; } + public ContactBuilder withProfilePicture(String url) { + this.profilePicture = new ProfilePicture(url); + return this; + } + public Contact build() { - return new Contact(name, phone, email, address, gitHubUsername, techStack, tags); + return new Contact(name, phone, email, address, gitHubUsername, techStack, tags, profilePicture); } }