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",
log: "log",
},
new: "new",
new: {
contact: "contact",
group: "group",
},
},
events: {
_id: {

@ -120,6 +120,7 @@ interface PropsType {
collections: CachedCollection[];
initialCollection?: string;
item?: ContactType;
group?: boolean;
onSave: (contact: ContactType, collectionUid: string, originalContact?: ContactType) => Promise<void>;
onDelete: (contact: ContactType, collectionUid: string) => void;
onCancel: () => void;
@ -142,6 +143,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
org: string;
note: string;
title: string;
group: boolean;
collectionUid: string;
showDeleteDialog: boolean;
@ -164,6 +166,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
org: "",
note: "",
title: "",
group: false,
collectionUid: "",
showDeleteDialog: false,
@ -172,6 +175,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
if (this.props.item !== undefined) {
const contact = this.props.item;
this.state.group = contact.group;
this.state.uid = contact.uid;
this.state.fn = contact.fn ? contact.fn : "";
if (contact.n) {
@ -301,6 +305,9 @@ class ContactEdit extends React.PureComponent<PropsType> {
comp.updatePropertyWithValue("version", "4.0");
comp.updatePropertyWithValue("uid", this.state.uid);
comp.updatePropertyWithValue("rev", ICAL.Time.now());
if (this.props.group) {
comp.updatePropertyWithValue("kind", "group");
}
const lastName = this.state.lastName.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) {
comp.removeAllProperties(name);
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)
.then(() => {
@ -390,7 +399,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
return (
<React.Fragment>
<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>
<form style={styles.form} onSubmit={this.onSubmit}>
<FormControl disabled={this.props.item !== undefined} style={styles.fullWidth}>
@ -408,163 +417,175 @@ class ContactEdit extends React.PureComponent<PropsType> {
</Select>
</FormControl>
<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 })
)}
{this.props.group || this.state.group ?
<TextField
name="firstName"
placeholder="Name"
style={{ marginTop: "2rem", ...styles.fullWidth }}
value={this.state.firstName}
onChange={this.handleInputChange}
/>
))}
:
<>
<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>
Emails
<IconButton
onClick={() => this.addValueType("email")}
title="Add email address"
>
<IconAdd />
</IconButton>
</div>
{this.state.email.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="email"
placeholder="Email"
types={emailTypes}
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/>
))}
<div>
Emails
<IconButton
onClick={() => this.addValueType("email")}
title="Add email address"
>
<IconAdd />
</IconButton>
</div>
{this.state.email.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="email"
placeholder="Email"
types={emailTypes}
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/>
))}
<div>
IMPP
<IconButton
onClick={() => this.addValueType("impp", "jabber")}
title="Add impp address"
>
<IconAdd />
</IconButton>
</div>
{this.state.impp.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="impp"
placeholder="IMPP"
types={imppTypes}
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/>
))}
<div>
IMPP
<IconButton
onClick={() => this.addValueType("impp", "jabber")}
title="Add impp address"
>
<IconAdd />
</IconButton>
</div>
{this.state.impp.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="impp"
placeholder="IMPP"
types={imppTypes}
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/>
))}
<div>
Addresses
<IconButton
onClick={() => this.addValueType("address")}
title="Add address"
>
<IconAdd />
</IconButton>
</div>
{this.state.address.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="address"
placeholder="Address"
types={addressTypes}
multiline
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/>
))}
<TextField
name="org"
placeholder="Organization"
style={styles.fullWidth}
value={this.state.org}
onChange={this.handleInputChange}
/>
<TextField
name="title"
placeholder="Title"
style={styles.fullWidth}
value={this.state.title}
onChange={this.handleInputChange}
/>
<TextField
name="note"
multiline
placeholder="Note"
style={styles.fullWidth}
value={this.state.note}
onChange={this.handleInputChange}
/>
<div>
Addresses
<IconButton
onClick={() => this.addValueType("address")}
title="Add address"
>
<IconAdd />
</IconButton>
</div>
{this.state.address.map((x, idx) => (
<ValueTypeComponent
key={idx}
name="address"
placeholder="Address"
types={addressTypes}
multiline
value={x}
onClearRequest={(name: string) => this.removeValueType(name, idx)}
onChange={(name: string, type: string, value: string) => (
this.handleValueTypeChange(name, idx, { type, value })
)}
/>
))}
<TextField
name="org"
placeholder="Organization"
style={styles.fullWidth}
value={this.state.org}
onChange={this.handleInputChange}
/>
<TextField
name="title"
placeholder="Title"
style={styles.fullWidth}
value={this.state.title}
onChange={this.handleInputChange}
/>
<TextField
name="note"
multiline
placeholder="Note"
style={styles.fullWidth}
value={this.state.note}
onChange={this.handleInputChange}
/>
</>
}
<div style={styles.submit}>
<Button
@ -605,7 +626,7 @@ class ContactEdit extends React.PureComponent<PropsType> {
onOk={() => this.props.onDelete(this.props.item!, this.props.initialCollection!)}
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>
</React.Fragment>
);

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

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

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

Loading…
Cancel
Save