Merge pull request #2277 from matrix-org/travis/terms-auth-improvements

Improve terms auth flow
This commit is contained in:
Travis Ralston 2018-11-16 12:36:17 -07:00 committed by GitHub
commit 2408eeeb3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 8 deletions

View File

@ -35,8 +35,24 @@ limitations under the License.
margin-bottom: 5px;
}
.mx_InteractiveAuthEntryComponents_termsSubmit {
margin-top: 20px;
margin-bottom: 5px;
display: block;
width: 100%;
}
// XXX: This should be a common button class
.mx_InteractiveAuthEntryComponents_msisdnSubmit:disabled {
background-color: $light-fg-color;
cursor: default;
}
.mx_InteractiveAuthEntryComponents_termsSubmit:disabled {
background-color: $accent-color-50pct;
cursor: default;
}
.mx_InteractiveAuthEntryComponents_termsPolicy {
display: block;
}

View File

@ -12,6 +12,7 @@ $light-fg-color: #747474;
// button UI (white-on-green in light skin)
$accent-fg-color: $primary-bg-color;
$accent-color: #76CFA6;
$accent-color-50pct: #76CFA67F;
$selection-fg-color: $primary-fg-color;

View File

@ -18,6 +18,7 @@ $focus-bg-color: #dddddd;
// button UI (white-on-green in light skin)
$accent-fg-color: #ffffff;
$accent-color: #76CFA6;
$accent-color-50pct: #76CFA67F;
$selection-fg-color: $primary-bg-color;

View File

@ -45,7 +45,7 @@ export async function startAnyRegistrationFlow(options) {
// caution though.
const hasIlagFlow = flows.some((flow) => {
return flow.stages.every((stage) => {
return ['m.login.dummy', 'm.login.recaptcha'].includes(stage);
return ['m.login.dummy', 'm.login.recaptcha', 'm.login.terms'].includes(stage);
});
});

View File

@ -68,6 +68,11 @@ export default React.createClass({
// If true, poll to see if the auth flow has been completed
// out-of-band
poll: PropTypes.bool,
// If true, components will be told that the 'Continue' button
// is managed by some other party and should not be managed by
// the component itself.
continueIsManaged: PropTypes.bool,
},
getInitialState: function() {
@ -128,6 +133,12 @@ export default React.createClass({
}
},
tryContinue: function() {
if (this.refs.stageComponent && this.refs.stageComponent.tryContinue) {
this.refs.stageComponent.tryContinue();
}
},
_authStateUpdated: function(stageType, stageState) {
const oldStage = this.state.authStage;
this.setState({
@ -192,6 +203,7 @@ export default React.createClass({
fail={this._onAuthStageFailed}
setEmailSid={this._setEmailSid}
makeRegistrationUrl={this.props.makeRegistrationUrl}
showContinue={!this.props.continueIsManaged}
/>
);
},

View File

@ -101,6 +101,9 @@ export default React.createClass({
},
onSubmit: function(ev) {
if (this.refs.uiAuth) {
this.refs.uiAuth.tryContinue();
}
this.setState({
doingUIAuth: true,
});
@ -217,6 +220,8 @@ export default React.createClass({
onAuthFinished={this._onUIAuthFinished}
inputs={{}}
poll={true}
ref="uiAuth"
continueIsManaged={true}
/>;
}
const inputClasses = classnames({

View File

@ -222,6 +222,7 @@ export const TermsAuthEntry = React.createClass({
stageParams: PropTypes.object.isRequired,
errorText: PropTypes.string,
busy: PropTypes.bool,
showContinue: PropTypes.bool,
},
componentWillMount: function() {
@ -275,19 +276,30 @@ export const TermsAuthEntry = React.createClass({
});
},
_trySubmit: function(policyId) {
tryContinue: function() {
this._trySubmit();
},
_togglePolicy: function(policyId) {
const newToggles = {};
let allChecked = true;
for (const policy of this.state.policies) {
let checked = this.state.toggledPolicies[policy.id];
if (policy.id === policyId) checked = !checked;
newToggles[policy.id] = checked;
}
this.setState({"toggledPolicies": newToggles});
},
_trySubmit: function() {
let allChecked = true;
for (const policy of this.state.policies) {
let checked = this.state.toggledPolicies[policy.id];
allChecked = allChecked && checked;
}
this.setState({"toggledPolicies": newToggles});
if (allChecked) this.props.submitAuthDict({type: TermsAuthEntry.LOGIN_TYPE});
else this.setState({errorText: _t("Please review and accept all of the homeserver's policies")});
},
render: function() {
@ -303,27 +315,35 @@ export const TermsAuthEntry = React.createClass({
allChecked = allChecked && checked;
checkboxes.push(
<label key={"policy_checkbox_" + policy.id}>
<input type="checkbox" onClick={() => this._trySubmit(policy.id)} checked={checked} />
<label key={"policy_checkbox_" + policy.id} className="mx_InteractiveAuthEntryComponents_termsPolicy">
<input type="checkbox" onClick={() => this._togglePolicy(policy.id)} checked={checked} />
<a href={policy.url} target="_blank" rel="noopener">{ policy.name }</a>
</label>,
);
}
let errorSection;
if (this.props.errorText) {
if (this.props.errorText || this.state.errorText) {
errorSection = (
<div className="error" role="alert">
{ this.props.errorText }
{ this.props.errorText || this.state.errorText }
</div>
);
}
let submitButton;
if (this.props.showContinue !== false) {
// XXX: button classes
submitButton = <button className="mx_InteractiveAuthEntryComponents_termsSubmit mx_UserSettings_button"
onClick={this._trySubmit} disabled={!allChecked}>{_t("Accept")}</button>;
}
return (
<div>
<p>{_t("Please review and accept the policies of this homeserver:")}</p>
{ checkboxes }
{ errorSection }
{ submitButton }
</div>
);
},

View File

@ -648,6 +648,7 @@
"Dismiss": "Dismiss",
"To continue, please enter your password.": "To continue, please enter your password.",
"Password:": "Password:",
"Please review and accept all of the homeserver's policies": "Please review and accept all of the homeserver's policies",
"Please review and accept the policies of this homeserver:": "Please review and accept the policies of this homeserver:",
"An email has been sent to %(emailAddress)s": "An email has been sent to %(emailAddress)s",
"Please check your email to continue registration.": "Please check your email to continue registration.",