From 250565070888f4f0b504677816cf2471552864a8 Mon Sep 17 00:00:00 2001 From: Ramzan Date: Wed, 28 Oct 2020 22:07:25 -0400 Subject: [PATCH] ContactEdit: add group editor --- src/Contacts/ContactEdit.tsx | 99 ++++++++++++++++++++++++++++++++---- src/Contacts/Main.tsx | 6 ++- 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/src/Contacts/ContactEdit.tsx b/src/Contacts/ContactEdit.tsx index 18636f1..91b32a1 100644 --- a/src/Contacts/ContactEdit.tsx +++ b/src/Contacts/ContactEdit.tsx @@ -27,6 +27,7 @@ import * as ICAL from "ical.js"; import { ContactType } from "../pim-types"; import { History } from "history"; +import Autocomplete from "@material-ui/lab/Autocomplete"; const telTypes = [ { type: "Home" }, @@ -125,6 +126,7 @@ interface PropsType { onDelete: (contact: ContactType, collectionUid: string) => void; onCancel: () => void; history: History; + groups: ContactType[]; } class ContactEdit extends React.PureComponent { @@ -147,6 +149,9 @@ class ContactEdit extends React.PureComponent { collectionUid: string; showDeleteDialog: boolean; + collectionGroups: ContactType[]; + newGroups: (string | ContactType)[]; + originalGroups: ContactType[]; }; constructor(props: PropsType) { @@ -170,6 +175,9 @@ class ContactEdit extends React.PureComponent { collectionUid: "", showDeleteDialog: false, + collectionGroups: [], + newGroups: [], + originalGroups: [], }; if (this.props.item !== undefined) { @@ -235,9 +243,21 @@ class ContactEdit extends React.PureComponent { } else if (props.collections[0]) { this.state.collectionUid = props.collections[0].collection.uid; } + + this.state.collectionGroups = this.props.groups.filter((group) => this.state.collectionUid === group.collectionUid); + this.state.collectionGroups.forEach((group) => { + if (group.members.includes(this.state.uid)) { + this.state.newGroups.push(group); + this.state.originalGroups.push(group); + } + }); + this.onSubmit = this.onSubmit.bind(this); + this.addMetadata = this.addMetadata.bind(this); this.handleChange = this.handleChange.bind(this); this.handleInputChange = this.handleInputChange.bind(this); + this.handleCollectionChange = this.handleCollectionChange.bind(this); + this.reloadGroupSuggestions = this.reloadGroupSuggestions.bind(this); this.handleValueTypeChange = this.handleValueTypeChange.bind(this); this.addValueType = this.addValueType.bind(this); this.removeValueType = this.removeValueType.bind(this); @@ -278,11 +298,24 @@ class ContactEdit extends React.PureComponent { }); } - public handleChange(name: string, value: string) { + public handleChange(name: string, value: string | (string | ContactType)[]) { this.setState({ [name]: value, }); + } + + public reloadGroupSuggestions(collectionUid: string) { + this.setState({ + collectionGroups: this.props.groups.filter((group) => collectionUid === group.collectionUid), + newGroups: [], + }); + } + public handleCollectionChange(contact: any) { + const name = contact.target.name; + const value = contact.target.value; + this.reloadGroupSuggestions(value); + this.handleChange(name, value); } public handleInputChange(contact: any) { @@ -291,6 +324,17 @@ class ContactEdit extends React.PureComponent { this.handleChange(name, value); } + public addMetadata(item: ContactType, uid: string, isGroup?: boolean) { + const comp = item.comp; + comp.updatePropertyWithValue("prodid", "-//iCal.js EteSync Web"); + comp.updatePropertyWithValue("version", "4.0"); + comp.updatePropertyWithValue("uid", uid); + comp.updatePropertyWithValue("rev", ICAL.Time.now()); + if (isGroup) { + comp.updatePropertyWithValue("kind", "group"); + } + } + public onSubmit(e: React.FormEvent) { e.preventDefault(); @@ -301,13 +345,32 @@ class ContactEdit extends React.PureComponent { ; const comp = contact.comp; - comp.updatePropertyWithValue("prodid", "-//iCal.js EteSync Web"); - comp.updatePropertyWithValue("version", "4.0"); - comp.updatePropertyWithValue("uid", this.state.uid); - comp.updatePropertyWithValue("rev", ICAL.Time.now()); - if (this.props.newGroup) { - comp.updatePropertyWithValue("kind", "group"); - } + this.addMetadata(contact, this.state.uid, this.props.newGroup); + + // Add new groups + this.state.newGroups.forEach((group) => { + if (typeof(group) === "string") { + const newGroup = new ContactType(new ICAL.Component(["vcard", [], []])); + this.addMetadata(newGroup, uuid.v4(), true); + newGroup.comp.updatePropertyWithValue("fn", group); + newGroup.comp.updatePropertyWithValue("member", `urn:uuid:${this.state.uid}`); + this.props.onSave(newGroup, this.state.collectionUid, undefined); + } else if (!this.state.originalGroups.includes(group)) { + const updatedGroup = group.clone(); + updatedGroup.comp.updatePropertyWithValue("member", `urn:uuid:${this.state.uid}`); + this.props.onSave(updatedGroup, this.state.collectionUid, group); + } + }); + + // Remove deleted groups + this.state.originalGroups.filter((x) => !this.state.newGroups.includes(x)).forEach((deletedGroup) => { + const updatedGroup = deletedGroup.clone(); + const members = updatedGroup.members.filter((uid) => uid !== this.state.uid); + updatedGroup.comp.removeAllProperties("member"); + members.forEach((m) => updatedGroup.comp.updatePropertyWithValue("member", `urn:uuid:${m}`)); + this.props.onSave(updatedGroup, this.state.collectionUid, deletedGroup); + }); + const lastName = this.state.lastName.trim(); const firstName = this.state.firstName.trim(); @@ -409,7 +472,7 @@ class ContactEdit extends React.PureComponent {