Initial version of contact editing.
parent
9521e3dae3
commit
6d76559d08
@ -0,0 +1,299 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import IconButton from 'material-ui/IconButton';
|
||||||
|
import RaisedButton from 'material-ui/RaisedButton';
|
||||||
|
import TextField from 'material-ui/TextField';
|
||||||
|
import SelectField from 'material-ui/SelectField';
|
||||||
|
import MenuItem from 'material-ui/MenuItem';
|
||||||
|
|
||||||
|
import IconAdd from 'material-ui/svg-icons/content/add';
|
||||||
|
import IconClear from 'material-ui/svg-icons/content/clear';
|
||||||
|
|
||||||
|
import * as uuid from 'uuid';
|
||||||
|
import * as ICAL from 'ical.js';
|
||||||
|
|
||||||
|
import * as EteSync from './api/EteSync';
|
||||||
|
|
||||||
|
import { ContactType } from './pim-types';
|
||||||
|
|
||||||
|
const TypeSelector = (props: any) => {
|
||||||
|
const types = [
|
||||||
|
{type: 'Home'},
|
||||||
|
{type: 'Work'},
|
||||||
|
{type: 'Other'},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SelectField
|
||||||
|
style={props.style}
|
||||||
|
value={props.value}
|
||||||
|
onChange={props.onChange}
|
||||||
|
>
|
||||||
|
{types.map((x) => (
|
||||||
|
<MenuItem key={x.type} value={x.type.toLowerCase()} primaryText={x.type} />
|
||||||
|
))}
|
||||||
|
</SelectField>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ValueType {
|
||||||
|
type: string;
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
constructor(type?: string, value?: string) {
|
||||||
|
this.type = type ? type : 'home';
|
||||||
|
this.value = value ? value : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ValueTypeComponentProps {
|
||||||
|
type?: string;
|
||||||
|
style?: object;
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
hintText: string;
|
||||||
|
value: ValueType;
|
||||||
|
onClearRequest: (name: string) => void;
|
||||||
|
onChange: (name: string, type: string, value: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ValueTypeComponent = (props: ValueTypeComponentProps) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<TextField
|
||||||
|
type={props.type}
|
||||||
|
name={props.name}
|
||||||
|
hintText={props.hintText}
|
||||||
|
style={props.style}
|
||||||
|
value={props.value.value}
|
||||||
|
onChange={(event: any) => props.onChange(props.name, props.value.type, event.target.value)}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => props.onClearRequest(props.name)}
|
||||||
|
tooltip="Remove"
|
||||||
|
>
|
||||||
|
<IconClear />
|
||||||
|
</IconButton>
|
||||||
|
<TypeSelector
|
||||||
|
value={props.value.type}
|
||||||
|
onChange={
|
||||||
|
(contact: object, key: number, payload: any) => props.onChange(props.name, payload, props.value.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ContactEdit extends React.Component {
|
||||||
|
state: {
|
||||||
|
uid: string,
|
||||||
|
fn: string;
|
||||||
|
phones: ValueType[];
|
||||||
|
emails: ValueType[];
|
||||||
|
|
||||||
|
journalUid: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
props: {
|
||||||
|
collections: Array<EteSync.CollectionInfo>,
|
||||||
|
initialCollection?: string,
|
||||||
|
contact?: ContactType,
|
||||||
|
onSave: (contact: ContactType, journalUid: string, originalContact?: ContactType) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
uid: '',
|
||||||
|
fn: '',
|
||||||
|
phones: [new ValueType()],
|
||||||
|
emails: [new ValueType()],
|
||||||
|
|
||||||
|
journalUid: '',
|
||||||
|
};
|
||||||
|
if (this.props.contact !== undefined) {
|
||||||
|
const contact = this.props.contact;
|
||||||
|
|
||||||
|
this.state.uid = contact.uid;
|
||||||
|
this.state.fn = contact.fn ? contact.fn : '';
|
||||||
|
} else {
|
||||||
|
this.state.uid = uuid.v4();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.collections[0]) {
|
||||||
|
this.state.journalUid = props.collections[0].uid;
|
||||||
|
}
|
||||||
|
this.onSubmit = this.onSubmit.bind(this);
|
||||||
|
this.handleChange = this.handleChange.bind(this);
|
||||||
|
this.handleInputChange = this.handleInputChange.bind(this);
|
||||||
|
this.handleValueTypeChange = this.handleValueTypeChange.bind(this);
|
||||||
|
this.addValueType = this.addValueType.bind(this);
|
||||||
|
this.removeValueType = this.removeValueType.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps: any) {
|
||||||
|
if (this.props.collections !== nextProps.collections) {
|
||||||
|
if (nextProps.collections[0]) {
|
||||||
|
this.setState({journalUid: nextProps.collections[0].uid});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addValueType(name: string) {
|
||||||
|
this.setState((prevState, props) => {
|
||||||
|
let newArray = prevState[name].slice(0);
|
||||||
|
newArray.push(new ValueType());
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
[name]: newArray,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeValueType(name: string, idx: number) {
|
||||||
|
this.setState((prevState, props) => {
|
||||||
|
let newArray = prevState[name].slice(0);
|
||||||
|
newArray.splice(idx, 1);
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
[name]: newArray,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleValueTypeChange(name: string, idx: number, value: ValueType) {
|
||||||
|
this.setState((prevState, props) => {
|
||||||
|
let newArray = prevState[name].slice(0);
|
||||||
|
newArray[idx] = value;
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
[name]: newArray,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(name: string, value: string) {
|
||||||
|
this.setState({
|
||||||
|
[name]: value
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInputChange(contact: any) {
|
||||||
|
const name = contact.target.name;
|
||||||
|
const value = contact.target.value;
|
||||||
|
this.handleChange(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(e: any) {
|
||||||
|
e.prcontactDefault();
|
||||||
|
|
||||||
|
let contact = new ContactType(new ICAL.Component(['vcard', []]));
|
||||||
|
// contact.uid = this.state.uid;
|
||||||
|
// contact.fn = this.state.fn;
|
||||||
|
|
||||||
|
this.props.onSave(contact, this.state.journalUid, this.props.contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const styles = {
|
||||||
|
form: {
|
||||||
|
},
|
||||||
|
fullWidth: {
|
||||||
|
width: '100%',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
|
submit: {
|
||||||
|
marginTop: 40,
|
||||||
|
textAlign: 'right',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<h2>
|
||||||
|
{this.props.contact ? 'Edit Contact' : 'New Contact'}
|
||||||
|
</h2>
|
||||||
|
<form style={styles.form} onSubmit={this.onSubmit}>
|
||||||
|
<SelectField
|
||||||
|
style={styles.fullWidth}
|
||||||
|
value={this.state.journalUid}
|
||||||
|
floatingLabelText="Saving to"
|
||||||
|
disabled={this.props.contact !== undefined}
|
||||||
|
onChange={(contact: object, key: number, payload: any) => this.handleChange('journalUid', payload)}
|
||||||
|
>
|
||||||
|
{this.props.collections.map((x) => (
|
||||||
|
<MenuItem key={x.uid} value={x.uid} primaryText={x.displayName} />
|
||||||
|
))}
|
||||||
|
</SelectField>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
name="fn"
|
||||||
|
hintText="Name"
|
||||||
|
style={styles.fullWidth}
|
||||||
|
value={this.state.fn}
|
||||||
|
onChange={this.handleInputChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Phone numbers
|
||||||
|
<IconButton
|
||||||
|
onClick={() => this.addValueType('phones')}
|
||||||
|
tooltip="Add phone number"
|
||||||
|
>
|
||||||
|
<IconAdd />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
{this.state.phones.map((x, idx) => (
|
||||||
|
<ValueTypeComponent
|
||||||
|
key={idx}
|
||||||
|
name="phones"
|
||||||
|
hintText="Phone"
|
||||||
|
value={this.state.phones[idx]}
|
||||||
|
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('emails')}
|
||||||
|
tooltip="Add email address"
|
||||||
|
>
|
||||||
|
<IconAdd />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
{this.state.emails.map((x, idx) => (
|
||||||
|
<ValueTypeComponent
|
||||||
|
key={idx}
|
||||||
|
name="emails"
|
||||||
|
hintText="Email"
|
||||||
|
value={this.state.emails[idx]}
|
||||||
|
onClearRequest={(name: string) => this.removeValueType(name, idx)}
|
||||||
|
onChange={(name: string, type: string, value: string) => (
|
||||||
|
this.handleValueTypeChange(name, idx, {type, value})
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<div style={styles.submit}>
|
||||||
|
<RaisedButton
|
||||||
|
type="submit"
|
||||||
|
label="Save"
|
||||||
|
secondary={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Not all types are supported at the moment. If you are editing a contact,
|
||||||
|
the unsupported types will be copied as is.
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ContactEdit;
|
Loading…
Reference in New Issue