Contacts: add new group button and adjust ContactEdit for group editing

master
Ramzan 4 years ago
parent 19444a38ba
commit 88be50f215

@ -44,7 +44,10 @@ export const routeResolver = new RouteResolver({
edit: "edit", edit: "edit",
log: "log", log: "log",
}, },
new: "new", new: {
contact: "contact",
group: "group",
},
}, },
events: { events: {
_id: { _id: {

@ -120,6 +120,7 @@ interface PropsType {
collections: CachedCollection[]; collections: CachedCollection[];
initialCollection?: string; initialCollection?: string;
item?: ContactType; item?: ContactType;
group?: boolean;
onSave: (contact: ContactType, collectionUid: string, originalContact?: ContactType) => Promise<void>; onSave: (contact: ContactType, collectionUid: string, originalContact?: ContactType) => Promise<void>;
onDelete: (contact: ContactType, collectionUid: string) => void; onDelete: (contact: ContactType, collectionUid: string) => void;
onCancel: () => void; onCancel: () => void;
@ -142,6 +143,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
org: string; org: string;
note: string; note: string;
title: string; title: string;
group: boolean;
collectionUid: string; collectionUid: string;
showDeleteDialog: boolean; showDeleteDialog: boolean;
@ -164,6 +166,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
org: "", org: "",
note: "", note: "",
title: "", title: "",
group: false,
collectionUid: "", collectionUid: "",
showDeleteDialog: false, showDeleteDialog: false,
@ -172,6 +175,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
if (this.props.item !== undefined) { if (this.props.item !== undefined) {
const contact = this.props.item; const contact = this.props.item;
this.state.group = contact.group;
this.state.uid = contact.uid; this.state.uid = contact.uid;
this.state.fn = contact.fn ? contact.fn : ""; this.state.fn = contact.fn ? contact.fn : "";
if (contact.n) { if (contact.n) {
@ -301,6 +305,9 @@ class ContactEdit extends React.PureComponent<PropsType> {
comp.updatePropertyWithValue("version", "4.0"); comp.updatePropertyWithValue("version", "4.0");
comp.updatePropertyWithValue("uid", this.state.uid); comp.updatePropertyWithValue("uid", this.state.uid);
comp.updatePropertyWithValue("rev", ICAL.Time.now()); comp.updatePropertyWithValue("rev", ICAL.Time.now());
if (this.props.group) {
comp.updatePropertyWithValue("kind", "group");
}
const lastName = this.state.lastName.trim(); const lastName = this.state.lastName.trim();
const firstName = this.state.firstName.trim(); const firstName = this.state.firstName.trim();
@ -341,13 +348,6 @@ class ContactEdit extends React.PureComponent<PropsType> {
}); });
} }
setProperties("tel", this.state.phone);
setProperties("email", this.state.email);
setProperties("adr", this.state.address);
setProperties("impp", this.state.impp.map((x) => (
{ type: x.type, value: x.type + ":" + x.value }
)));
function setProperty(name: string, value: string) { function setProperty(name: string, value: string) {
comp.removeAllProperties(name); comp.removeAllProperties(name);
if (value !== "") { if (value !== "") {
@ -355,10 +355,19 @@ class ContactEdit extends React.PureComponent<PropsType> {
} }
} }
setProperty("org", this.state.org);
setProperty("title", this.state.title);
setProperty("note", this.state.note);
if (!this.props.group && !this.state.group) {
setProperties("tel", this.state.phone);
setProperties("email", this.state.email);
setProperties("adr", this.state.address);
setProperties("impp", this.state.impp.map((x) => (
{ type: x.type, value: x.type + ":" + x.value }
)));
setProperty("org", this.state.org);
setProperty("title", this.state.title);
setProperty("note", this.state.note);
}
this.props.onSave(contact, this.state.collectionUid, this.props.item) this.props.onSave(contact, this.state.collectionUid, this.props.item)
.then(() => { .then(() => {
@ -390,7 +399,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
return ( return (
<React.Fragment> <React.Fragment>
<h2> <h2>
{this.props.item ? "Edit Contact" : "New Contact"} {this.props.item ? this.state.group ? "Edit Group" : "Edit Contact" : this.props.group ? "New Group" : "New Contact"}
</h2> </h2>
<form style={styles.form} onSubmit={this.onSubmit}> <form style={styles.form} onSubmit={this.onSubmit}>
<FormControl disabled={this.props.item !== undefined} style={styles.fullWidth}> <FormControl disabled={this.props.item !== undefined} style={styles.fullWidth}>
@ -408,163 +417,175 @@ class ContactEdit extends React.PureComponent<PropsType> {
</Select> </Select>
</FormControl> </FormControl>
<TextField {this.props.group || this.state.group ?
name="namePrefix" <TextField
placeholder="Prefix" name="firstName"
style={{ marginTop: "2rem", ...styles.fullWidth }} placeholder="Name"
value={this.state.namePrefix} style={{ marginTop: "2rem", ...styles.fullWidth }}
onChange={this.handleInputChange} value={this.state.firstName}
/> onChange={this.handleInputChange}
<TextField
name="firstName"
placeholder="First name"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.firstName}
onChange={this.handleInputChange}
/>
<TextField
name="middleName"
placeholder="Middle name"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.middleName}
onChange={this.handleInputChange}
/>
<TextField
name="lastName"
placeholder="Last name"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.lastName}
onChange={this.handleInputChange}
/>
<TextField
name="nameSuffix"
placeholder="Suffix"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.nameSuffix}
onChange={this.handleInputChange}
/>
<div>
Phone numbers
<IconButton
onClick={() => this.addValueType("phone")}
title="Add phone number"
>
<IconAdd />
</IconButton>
</div>
{this.state.phone.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="phone"
placeholder="Phone"
types={telTypes}
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/> />
))} :
<>
<TextField
name="namePrefix"
placeholder="Prefix"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.namePrefix}
onChange={this.handleInputChange}
/>
<TextField
name="firstName"
placeholder="First name"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.firstName}
onChange={this.handleInputChange}
/>
<TextField
name="middleName"
placeholder="Middle name"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.middleName}
onChange={this.handleInputChange}
/>
<TextField
name="lastName"
placeholder="Last name"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.lastName}
onChange={this.handleInputChange}
/>
<TextField
name="nameSuffix"
placeholder="Suffix"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.nameSuffix}
onChange={this.handleInputChange}
/>
<div>
Phone numbers
<IconButton
onClick={() => this.addValueType("phone")}
title="Add phone number"
>
<IconAdd />
</IconButton>
</div>
{this.state.phone.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="phone"
placeholder="Phone"
types={telTypes}
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/>
))}
<div> <div>
Emails Emails
<IconButton <IconButton
onClick={() => this.addValueType("email")} onClick={() => this.addValueType("email")}
title="Add email address" title="Add email address"
> >
<IconAdd /> <IconAdd />
</IconButton> </IconButton>
</div> </div>
{this.state.email.map((x, idx) => ( {this.state.email.map((x, idx) => (
<ValueTypeComponent <ValueTypeComponent
key={idx} key={idx}
name="email" name="email"
placeholder="Email" placeholder="Email"
types={emailTypes} types={emailTypes}
value={x} value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)} onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => ( onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value }) this.handleValueTypeChange(name, idx, { type, value })
)} )}
/> />
))} ))}
<div> <div>
IMPP IMPP
<IconButton <IconButton
onClick={() => this.addValueType("impp", "jabber")} onClick={() => this.addValueType("impp", "jabber")}
title="Add impp address" title="Add impp address"
> >
<IconAdd /> <IconAdd />
</IconButton> </IconButton>
</div> </div>
{this.state.impp.map((x, idx) => ( {this.state.impp.map((x, idx) => (
<ValueTypeComponent <ValueTypeComponent
key={idx} key={idx}
name="impp" name="impp"
placeholder="IMPP" placeholder="IMPP"
types={imppTypes} types={imppTypes}
value={x} value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)} onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => ( onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value }) this.handleValueTypeChange(name, idx, { type, value })
)} )}
/> />
))} ))}
<div> <div>
Addresses Addresses
<IconButton <IconButton
onClick={() => this.addValueType("address")} onClick={() => this.addValueType("address")}
title="Add address" title="Add address"
> >
<IconAdd /> <IconAdd />
</IconButton> </IconButton>
</div> </div>
{this.state.address.map((x, idx) => ( {this.state.address.map((x, idx) => (
<ValueTypeComponent <ValueTypeComponent
key={idx} key={idx}
name="address" name="address"
placeholder="Address" placeholder="Address"
types={addressTypes} types={addressTypes}
multiline multiline
value={x} value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)} onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => ( onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value }) this.handleValueTypeChange(name, idx, { type, value })
)} )}
/> />
))} ))}
<TextField <TextField
name="org" name="org"
placeholder="Organization" placeholder="Organization"
style={styles.fullWidth} style={styles.fullWidth}
value={this.state.org} value={this.state.org}
onChange={this.handleInputChange} onChange={this.handleInputChange}
/> />
<TextField <TextField
name="title" name="title"
placeholder="Title" placeholder="Title"
style={styles.fullWidth} style={styles.fullWidth}
value={this.state.title} value={this.state.title}
onChange={this.handleInputChange} onChange={this.handleInputChange}
/> />
<TextField <TextField
name="note" name="note"
multiline multiline
placeholder="Note" placeholder="Note"
style={styles.fullWidth} style={styles.fullWidth}
value={this.state.note} value={this.state.note}
onChange={this.handleInputChange} onChange={this.handleInputChange}
/> />
</>
}
<div style={styles.submit}> <div style={styles.submit}>
<Button <Button
@ -605,7 +626,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
onOk={() => this.props.onDelete(this.props.item!, this.props.initialCollection!)} onOk={() => this.props.onDelete(this.props.item!, this.props.initialCollection!)}
onCancel={() => this.setState({ showDeleteDialog: false })} onCancel={() => this.setState({ showDeleteDialog: false })}
> >
Are you sure you would like to delete this contact? {`Are you sure you would like to delete this ${this.state.group ? "group" : "contact"}?`}
</ConfirmationDialog> </ConfirmationDialog>
</React.Fragment> </React.Fragment>
); );

@ -99,15 +99,31 @@ export default function ContactsMain() {
onItemClick={(item) => history.push( onItemClick={(item) => history.push(
routeResolver.getRoute("pim.contacts._id", { itemUid: getItemNavigationUid(item) }) routeResolver.getRoute("pim.contacts._id", { itemUid: getItemNavigationUid(item) })
)} )}
onNewGroupClick={() => history.push(
routeResolver.getRoute("pim.contacts.new.group")
)}
/> />
<PimFab <PimFab
onClick={() => history.push( onClick={() => history.push(
routeResolver.getRoute("pim.contacts.new") routeResolver.getRoute("pim.contacts.new.contact")
)} )}
/> />
</Route> </Route>
<Route <Route
path={routeResolver.getRoute("pim.contacts.new")} path={routeResolver.getRoute("pim.contacts.new.group")}
exact
>
<ContactEdit
collections={cachedCollections}
onSave={onItemSave}
onDelete={onItemDelete}
onCancel={onCancel}
history={history}
group
/>
</Route>
<Route
path={routeResolver.getRoute("pim.contacts.new.contact")}
exact exact
> >
<ContactEdit <ContactEdit
@ -160,6 +176,7 @@ export default function ContactsMain() {
onDelete={onItemDelete} onDelete={onItemDelete}
onCancel={onCancel} onCancel={onCancel}
history={history} history={history}
group
/> />
</Route> </Route>
<Route <Route

@ -22,6 +22,7 @@ const useStyles = makeStyles((theme) => ({
interface PropsType { interface PropsType {
entries: ContactType[]; entries: ContactType[];
onItemClick: (contact: ContactType) => void; onItemClick: (contact: ContactType) => void;
onNewGroupClick: () => void;
} }
export default function SearchableAddressBook(props: PropsType) { export default function SearchableAddressBook(props: PropsType) {
@ -66,6 +67,7 @@ export default function SearchableAddressBook(props: PropsType) {
groups={groups} groups={groups}
filterByGroup={filterByGroup} filterByGroup={filterByGroup}
setFilterByGroup={setFilterByGroup} setFilterByGroup={setFilterByGroup}
newGroup={props.onNewGroupClick}
/> />
</Grid> </Grid>

@ -2,6 +2,9 @@ import * as React from "react";
import InboxIcon from "@material-ui/icons/Inbox"; import InboxIcon from "@material-ui/icons/Inbox";
import LabelIcon from "@material-ui/icons/LabelOutlined"; import LabelIcon from "@material-ui/icons/LabelOutlined";
import AddIcon from "@material-ui/icons/Add";
import IconButton from "@material-ui/core/IconButton";
import { List, ListItem, ListSubheader } from "../widgets/List"; import { List, ListItem, ListSubheader } from "../widgets/List";
import { ContactType } from "../pim-types"; import { ContactType } from "../pim-types";
@ -33,10 +36,11 @@ interface PropsType {
groups: ContactType[]; groups: ContactType[];
filterByGroup: string | undefined; filterByGroup: string | undefined;
setFilterByGroup: (group: string | undefined) => void; setFilterByGroup: (group: string | undefined) => void;
newGroup: () => void;
} }
export default React.memo(function Sidebar(props: PropsType) { export default React.memo(function Sidebar(props: PropsType) {
const { groups, filterByGroup, setFilterByGroup } = props; const { groups, filterByGroup, setFilterByGroup, newGroup } = props;
const groupList = [...groups].sort((a, b) => a.fn.localeCompare(b.fn)).map((group) => ( const groupList = [...groups].sort((a, b) => a.fn.localeCompare(b.fn)).map((group) => (
<SidebarListItem <SidebarListItem
@ -59,7 +63,18 @@ export default React.memo(function Sidebar(props: PropsType) {
setFilterByGroup={setFilterByGroup} setFilterByGroup={setFilterByGroup}
/> />
<ListSubheader>Groups</ListSubheader> <div style={{ display: "flex", justifyContent: "space-between" }}>
<ListSubheader>
Groups
</ListSubheader>
<IconButton
edge="end"
onClick={newGroup}
>
<AddIcon />
</IconButton>
</div>
{groupList} {groupList}
</List> </List>
); );

Loading…
Cancel
Save