ContactEdit: add group editor

master
Ramzan 4 years ago
parent e0e21cfbce
commit 2505650708

@ -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<any>;
groups: ContactType[];
}
class ContactEdit extends React.PureComponent<PropsType> {
@ -147,6 +149,9 @@ class ContactEdit extends React.PureComponent<PropsType> {
collectionUid: string;
showDeleteDialog: boolean;
collectionGroups: ContactType[];
newGroups: (string | ContactType)[];
originalGroups: ContactType[];
};
constructor(props: PropsType) {
@ -170,6 +175,9 @@ class ContactEdit extends React.PureComponent<PropsType> {
collectionUid: "",
showDeleteDialog: false,
collectionGroups: [],
newGroups: [],
originalGroups: [],
};
if (this.props.item !== undefined) {
@ -235,9 +243,21 @@ class ContactEdit extends React.PureComponent<PropsType> {
} 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<PropsType> {
});
}
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<PropsType> {
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<any>) {
e.preventDefault();
@ -301,13 +345,32 @@ class ContactEdit extends React.PureComponent<PropsType> {
;
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<PropsType> {
<Select
name="collectionUid"
value={this.state.collectionUid}
onChange={this.handleInputChange}
onChange={this.handleCollectionChange}
>
{this.props.collections.map((x) => (
<MenuItem key={x.collection.uid} value={x.collection.uid}>{x.metadata.name}</MenuItem>
@ -584,6 +647,24 @@ class ContactEdit extends React.PureComponent<PropsType> {
value={this.state.note}
onChange={this.handleInputChange}
/>
<Autocomplete
style={styles.fullWidth}
freeSolo
multiple
autoHighlight
options={this.state.collectionGroups}
getOptionLabel={(option: ContactType) => option.fn ?? option}
value={this.state.newGroups}
onChange={(_e, value) => this.handleChange("newGroups", value)}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
label="Groups"
fullWidth
/>
)}
/>
</>
}

@ -79,6 +79,8 @@ export default function ContactsMain() {
}
}
const groups = flatEntries.filter((x) => x.group);
const styles = {
button: {
marginLeft: theme.spacing(1),
@ -120,6 +122,7 @@ export default function ContactsMain() {
onCancel={onCancel}
history={history}
newGroup
groups={groups}
/>
</Route>
<Route
@ -132,6 +135,7 @@ export default function ContactsMain() {
onDelete={onItemDelete}
onCancel={onCancel}
history={history}
groups={groups}
/>
</Route>
<Route
@ -176,7 +180,7 @@ export default function ContactsMain() {
onDelete={onItemDelete}
onCancel={onCancel}
history={history}
newGroup
groups={groups}
/>
</Route>
<Route

Loading…
Cancel
Save