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 { ContactType } from "../pim-types";
import { History } from "history"; import { History } from "history";
import Autocomplete from "@material-ui/lab/Autocomplete";
const telTypes = [ const telTypes = [
{ type: "Home" }, { type: "Home" },
@ -125,6 +126,7 @@ interface PropsType {
onDelete: (contact: ContactType, collectionUid: string) => void; onDelete: (contact: ContactType, collectionUid: string) => void;
onCancel: () => void; onCancel: () => void;
history: History<any>; history: History<any>;
groups: ContactType[];
} }
class ContactEdit extends React.PureComponent<PropsType> { class ContactEdit extends React.PureComponent<PropsType> {
@ -147,6 +149,9 @@ class ContactEdit extends React.PureComponent<PropsType> {
collectionUid: string; collectionUid: string;
showDeleteDialog: boolean; showDeleteDialog: boolean;
collectionGroups: ContactType[];
newGroups: (string | ContactType)[];
originalGroups: ContactType[];
}; };
constructor(props: PropsType) { constructor(props: PropsType) {
@ -170,6 +175,9 @@ class ContactEdit extends React.PureComponent<PropsType> {
collectionUid: "", collectionUid: "",
showDeleteDialog: false, showDeleteDialog: false,
collectionGroups: [],
newGroups: [],
originalGroups: [],
}; };
if (this.props.item !== undefined) { if (this.props.item !== undefined) {
@ -235,9 +243,21 @@ class ContactEdit extends React.PureComponent<PropsType> {
} else if (props.collections[0]) { } else if (props.collections[0]) {
this.state.collectionUid = props.collections[0].collection.uid; 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.onSubmit = this.onSubmit.bind(this);
this.addMetadata = this.addMetadata.bind(this);
this.handleChange = this.handleChange.bind(this); this.handleChange = this.handleChange.bind(this);
this.handleInputChange = this.handleInputChange.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.handleValueTypeChange = this.handleValueTypeChange.bind(this);
this.addValueType = this.addValueType.bind(this); this.addValueType = this.addValueType.bind(this);
this.removeValueType = this.removeValueType.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({ this.setState({
[name]: value, [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) { public handleInputChange(contact: any) {
@ -291,6 +324,17 @@ class ContactEdit extends React.PureComponent<PropsType> {
this.handleChange(name, value); 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>) { public onSubmit(e: React.FormEvent<any>) {
e.preventDefault(); e.preventDefault();
@ -301,13 +345,32 @@ class ContactEdit extends React.PureComponent<PropsType> {
; ;
const comp = contact.comp; const comp = contact.comp;
comp.updatePropertyWithValue("prodid", "-//iCal.js EteSync Web"); this.addMetadata(contact, this.state.uid, this.props.newGroup);
comp.updatePropertyWithValue("version", "4.0");
comp.updatePropertyWithValue("uid", this.state.uid); // Add new groups
comp.updatePropertyWithValue("rev", ICAL.Time.now()); this.state.newGroups.forEach((group) => {
if (this.props.newGroup) { if (typeof(group) === "string") {
comp.updatePropertyWithValue("kind", "group"); 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 lastName = this.state.lastName.trim();
const firstName = this.state.firstName.trim(); const firstName = this.state.firstName.trim();
@ -409,7 +472,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
<Select <Select
name="collectionUid" name="collectionUid"
value={this.state.collectionUid} value={this.state.collectionUid}
onChange={this.handleInputChange} onChange={this.handleCollectionChange}
> >
{this.props.collections.map((x) => ( {this.props.collections.map((x) => (
<MenuItem key={x.collection.uid} value={x.collection.uid}>{x.metadata.name}</MenuItem> <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} value={this.state.note}
onChange={this.handleInputChange} 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 = { const styles = {
button: { button: {
marginLeft: theme.spacing(1), marginLeft: theme.spacing(1),
@ -120,6 +122,7 @@ export default function ContactsMain() {
onCancel={onCancel} onCancel={onCancel}
history={history} history={history}
newGroup newGroup
groups={groups}
/> />
</Route> </Route>
<Route <Route
@ -132,6 +135,7 @@ export default function ContactsMain() {
onDelete={onItemDelete} onDelete={onItemDelete}
onCancel={onCancel} onCancel={onCancel}
history={history} history={history}
groups={groups}
/> />
</Route> </Route>
<Route <Route
@ -176,7 +180,7 @@ export default function ContactsMain() {
onDelete={onItemDelete} onDelete={onItemDelete}
onCancel={onCancel} onCancel={onCancel}
history={history} history={history}
newGroup groups={groups}
/> />
</Route> </Route>
<Route <Route

Loading…
Cancel
Save