adding credential editing
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
// Enter one credential at a time.
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PhoneEdit from './phone-edit.jsx';
|
||||
import { parsePhoneNumber } from 'libphonenumber-js/mobile';
|
||||
|
||||
export default class CredentialEdit extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
tel: '',
|
||||
email: ''
|
||||
};
|
||||
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
this.handleEmailChange = this.handleEmailChange.bind(this);
|
||||
this.handlePhoneChange = this.handlePhoneChange.bind(this);
|
||||
}
|
||||
|
||||
formatPhoneNumber(raw) {
|
||||
const number = parsePhoneNumber(raw);
|
||||
return number ? number.formatInternational() : raw;
|
||||
}
|
||||
|
||||
handleEmailChange(e) {
|
||||
this.setState({email: e.target.value});
|
||||
}
|
||||
|
||||
handlePhoneChange(number) {
|
||||
console.log("handlePhoneChange", number);
|
||||
this.setState({tel: number});
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
const value = this.props.method == 'email' ? this.state.email : this.state.tel;
|
||||
console.log("handleSubmit", value);
|
||||
if (value) {
|
||||
this.props.onSubmit(value);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (<form className="panel-form-column" onSubmit={this.handleSubmit}>
|
||||
{this.props.method == 'email' ?
|
||||
<><div className="panel-form-row">
|
||||
<label className="large"><FormattedMessage id="change_email" defaultMessage="Change email"
|
||||
description="Prompt to change current email" /></label>
|
||||
</div>
|
||||
<div className="group">
|
||||
<label className="small gray">
|
||||
<FormattedMessage id="current_email" defaultMessage="Current email" description="Label for old email" />
|
||||
</label>
|
||||
</div></>
|
||||
: this.props.method == 'tel' ?
|
||||
<><div className="panel-form-row">
|
||||
<label className="large"><FormattedMessage id="change_phonel" defaultMessage="Change phone number"
|
||||
description="Prompt to change current phone number"/></label>
|
||||
</div>
|
||||
<div className="group">
|
||||
<label className="small gray">
|
||||
<FormattedMessage id="current_phone" defaultMessage="Current phone number" description="Label for old phone" />
|
||||
</label>
|
||||
</div></>
|
||||
: null}
|
||||
<div className="panel-form-row">
|
||||
<tt className="quoted">{this.formatPhoneNumber(this.props.val)}</tt>
|
||||
</div>
|
||||
{this.props.method == 'email' ?
|
||||
<><div className="group">
|
||||
<label className="small gray"><FormattedMessage id="new_email" defaultMessage="New email"
|
||||
description="Prompt for entering a new email" /></label>
|
||||
</div>
|
||||
<div className="group">
|
||||
<FormattedMessage id="email_prompt" defaultMessage="Email, e.g. jdoe@example.com"
|
||||
description="Input placeholder for email entry">{
|
||||
(email_prompt) => <input type="email" placeholder={email_prompt} autoComplete="email"
|
||||
value={this.state.email} onChange={this.handleEmailChange} required/>
|
||||
}</FormattedMessage>
|
||||
</div></>
|
||||
: this.props.method == 'tel' ?
|
||||
<><div className="group">
|
||||
<label className="small gray"><FormattedMessage id="new_phone_number" defaultMessage="New phone number"
|
||||
description="Prompt for entering a new telephone number" /></label>
|
||||
</div>
|
||||
<div className="panel-form-row">
|
||||
<PhoneEdit
|
||||
autoFocus={true}
|
||||
onShowCountrySelector={this.props.onShowCountrySelector}
|
||||
onSubmit={this.handlePhoneChange} />
|
||||
</div></>
|
||||
: null}
|
||||
<div className="dialog-buttons">
|
||||
<button className="secondary" onClick={this.props.onCancel}>
|
||||
<FormattedMessage id="button_cancel" defaultMessage="Cancel" description="Button [Cancel]" />
|
||||
</button>
|
||||
<button className="primary" type="submit" >
|
||||
<FormattedMessage id="button_ok" defaultMessage="OK" description="Button [OK]" />
|
||||
</button>
|
||||
</div>
|
||||
</form>);
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
// View for editing topic (including 'me' topic) parameters.
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import TopicDescEdit from '../widgets/topic-desc-edit.jsx';
|
||||
|
||||
import { arrayEqual, asEmail, asPhone } from '../lib/utils.js';
|
||||
|
||||
export default class TopicCommon extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const topic = this.props.tinode.getTopic(this.props.topic);
|
||||
const acs = topic.getAccessMode();
|
||||
this.state = {
|
||||
isMe: this.props.topic == 'me',
|
||||
owner: acs && acs.isOwner(),
|
||||
credentials: (topic.getCredentials ? topic.getCredentials() : null) || [],
|
||||
addCredActive: false,
|
||||
addCredInvalid: false,
|
||||
newCred: '',
|
||||
tags: []
|
||||
};
|
||||
|
||||
this.previousTagsUpdated = undefined;
|
||||
|
||||
this.onTagsUpdated = this.onTagsUpdated.bind(this);
|
||||
this.handleTagsUpdated = this.handleTagsUpdated.bind(this);
|
||||
this.tnCredsUpdated = this.tnCredsUpdated.bind(this);
|
||||
this.handleCredChange = this.handleCredChange.bind(this);
|
||||
this.handleCredKeyDown = this.handleCredKeyDown.bind(this);
|
||||
this.handleCredEntered = this.handleCredEntered.bind(this);
|
||||
}
|
||||
|
||||
// No need to separately handle component mount.
|
||||
componentDidUpdate(props) {
|
||||
const topic = this.props.tinode.getTopic(props.topic);
|
||||
if (!topic) {
|
||||
return;
|
||||
}
|
||||
|
||||
topic.onCredsUpdated = this.tnCredsUpdated;
|
||||
|
||||
if (topic.onTagsUpdated != this.onTagsUpdated) {
|
||||
if (topic.getType() == 'grp') {
|
||||
this.previousTagsUpdated = topic.onTagsUpdated;
|
||||
topic.onTagsUpdated = this.onTagsUpdated;
|
||||
} else {
|
||||
this.previousTagsUpdated = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.state.topic != props.topic) {
|
||||
this.setState({topic: props.topic});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const topic = this.props.tinode.getTopic(this.props.topic);
|
||||
topic.onCredsUpdated = undefined;
|
||||
topic.onTagsUpdated = this.previousTagsUpdated;
|
||||
}
|
||||
|
||||
tnCredsUpdated(creds) {
|
||||
this.setState({credentials: creds || []});
|
||||
}
|
||||
|
||||
handleCredChange(e) {
|
||||
this.setState({newCred: e.target.value, addCredInvalid: false});
|
||||
}
|
||||
|
||||
handleCredKeyDown(e) {
|
||||
if (e.keyCode === 27) {
|
||||
// Escape pressed
|
||||
this.setState({newCred: '', addCredActive: false});
|
||||
} else if (e.keyCode === 13) {
|
||||
// Enter pressed
|
||||
this.handleCredEntered(e);
|
||||
}
|
||||
}
|
||||
|
||||
handleCredEntered(e) {
|
||||
const value = this.state.newCred.trim();
|
||||
if (!value) {
|
||||
this.setState({addCredActive: false, addCredInvalid: false});
|
||||
return;
|
||||
}
|
||||
|
||||
let val = asPhone(value);
|
||||
let method;
|
||||
if (val) {
|
||||
method = 'tel';
|
||||
} else {
|
||||
val = asEmail(value);
|
||||
if (val) {
|
||||
method = 'email';
|
||||
}
|
||||
}
|
||||
if (method) {
|
||||
this.props.onCredAdd(method, val);
|
||||
this.setState({addCredActive: false, newCred: ''});
|
||||
} else {
|
||||
this.setState({addCredInvalid: true});
|
||||
}
|
||||
}
|
||||
|
||||
// Server informs that the tags have been updated.
|
||||
onTagsUpdated(tags) {
|
||||
this.setState({tags: tags});
|
||||
|
||||
if (this.previousTagsUpdated && this.previousTagsUpdated != this.onTagsUpdated) {
|
||||
this.previousTagsUpdated(tags);
|
||||
}
|
||||
}
|
||||
|
||||
// Request server to change tags.
|
||||
handleTagsUpdated(tags) {
|
||||
if (!arrayEqual(this.state.tags.slice(0), tags.slice(0))) {
|
||||
this.props.onUpdateTagsRequest(this.props.topic, tags);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const credentials = [];
|
||||
if (this.state.isMe) {
|
||||
this.state.credentials.map((cred) => {
|
||||
credentials.push(
|
||||
<div key={cred.meth + ":" + cred.val + ":" + cred.done}>{cred.meth}: <tt>{cred.val}</tt>
|
||||
<span> {!cred.done ?
|
||||
<a href="#" onClick={(e) => {e.preventDefault(); this.props.onCredConfirm(cred.meth, cred.val);}}>
|
||||
<FormattedMessage id="validate_credential_action" defaultMessage="confirm"
|
||||
description="Validate credentail call to action" />
|
||||
</a>
|
||||
: null} <a href="#" onClick={(e) => {e.preventDefault(); this.props.onCredDelete(cred.meth, cred.val);}}><i
|
||||
className="material-icons gray">delete_outline</i></a></span>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="scrollable-panel">
|
||||
<TopicDescEdit
|
||||
tinode={this.props.tinode}
|
||||
topic={this.props.topic}
|
||||
onUpdateTopicDesc={this.props.onUpdateTopicDesc}
|
||||
onUpdateTags={this.handleTagsUpdated}
|
||||
onError={this.props.onError} />
|
||||
{this.state.isMe ?
|
||||
<>
|
||||
<div className="hr" />
|
||||
<div className="panel-form-column">
|
||||
<label className="small">
|
||||
<FormattedMessage id="label_user_contacts" defaultMessage="Contacts:"
|
||||
description="Label for user contacts" />
|
||||
</label>
|
||||
<div className="quoted">
|
||||
{credentials}
|
||||
{this.state.addCredActive ?
|
||||
<FormattedMessage id="phone_or_email_prompt" defaultMessage="Phone number or email"
|
||||
description="Placeholer for phone or email">{(phone_or_email_prompt) =>
|
||||
<input type="text" value={this.state.value}
|
||||
className={this.state.addCredInvalid ? 'invalid' : null}
|
||||
placeholder={phone_or_email_prompt} required="required" autoFocus
|
||||
onChange={this.handleCredChange} onKeyDown={this.handleCredKeyDown} onBlur={this.handleCredEntered} />
|
||||
}</FormattedMessage>
|
||||
: null}
|
||||
<div>
|
||||
<a href="#" onClick={(e) => {e.preventDefault(); this.setState({addCredActive: true});}}>
|
||||
<i className="material-icons">add</i>
|
||||
<FormattedMessage id="button_add_another" defaultMessage="Add another" description="Call to action [+ add another]" />
|
||||
</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user