passbolt-styleguide
Version:
Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.
206 lines (188 loc) • 5.79 kB
JavaScript
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) 2020 Passbolt SA (https://www.passbolt.com)
*
* Licensed under GNU Affero General Public License version 3 of the or any later version.
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) 2020 Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 2.12.0
*/
import React, { Component } from "react";
import { withProgress } from "../../../../contexts/ProgressContext";
import { Trans, withTranslation } from "react-i18next";
import PropTypes from "prop-types";
import SpinnerSVG from "../../../../../img/svg/spinner.svg";
class DisplayProgress extends Component {
/**
* Default constructor
* @param props Component props
*/
constructor(props) {
super(props);
this.infiniteTimerUpdateIntervalId = null; // The infinite timer update interval ID
this.state = this.defaultState;
}
/**
* Returns the component default state
* @return {object}
*/
get defaultState() {
return {
infiniteTimer: 0, // The timer for the infinite calculation, used only if infinite progress mode.
};
}
/**
* Component did mount
*/
componentDidMount() {
this.startInfiniteTimerUpdateProgress();
}
/**
* Start the infinite timer update.
* @return {void}
*/
startInfiniteTimerUpdateProgress() {
if (!this.isInfiniteProgressMode()) {
return;
}
this.infiniteTimerUpdateIntervalId = setInterval(() => {
this.setState({ infiniteTimer: this.state.infiniteTimer + 2 });
}, 500);
}
/**
* Component did update
* @return {void}
*/
componentDidUpdate() {
if (!this.isInfiniteProgressMode() && this.infiniteTimerUpdateIntervalId) {
this.resetInterval();
}
}
/**
* Component will unmount
*/
componentWillUnmount() {
this.resetInterval();
}
/**
* Check if the component should display an infinite progress bar.
* @returns {boolean}
*/
isInfiniteProgressMode() {
return !this.props.progressContext.progressDialogProps?.goals;
}
/**
* Reset interval
*/
resetInterval() {
if (this.infiniteTimerUpdateIntervalId) {
clearInterval(this.infiniteTimerUpdateIntervalId);
this.infiniteTimerUpdateIntervalId = null;
}
}
/**
* Calculate the progress
* @return {number}
*/
calculateProgress() {
if (this.props.progressContext.progressDialogProps?.goals > 0) {
return this.calculateGoalsProgress();
} else {
return this.calculateInfiniteProgress();
}
}
/**
* Calculate the infinite progress
* @return {number}
*/
calculateInfiniteProgress() {
return 100 - 100 / Math.pow(1.1, this.state.infiniteTimer);
}
/**
* Calculate the progress based on the goals
* @return {number}
*/
calculateGoalsProgress() {
const completed = this.props.progressContext.progressDialogProps?.completed || 0;
let progress = Math.round((100 * completed) / this.props.progressContext.progressDialogProps?.goals);
if (progress > 100) {
progress = 100;
}
return progress;
}
/**
* Decode html characters
* @param {string} text with html encoded characters
* @return {string}
*/
decodedHtmlCharacters(text) {
if (text) {
try {
const doc = new DOMParser().parseFromString(text, "text/html");
return doc.documentElement.textContent;
} catch (error) {
console.error(error);
}
}
return text;
}
/**
* Render
* @returns {JSX.Element}
*/
render() {
const progress = this.calculateProgress();
const progressBarStyle = { width: `${progress}%` };
return (
<div className="dialog-wrapper progress-dialog">
<div className="dialog">
<div className="dialog-header">
<span className="dialog-title-wrapper">
<h2>
{this.decodedHtmlCharacters(this.props.progressContext.progressDialogProps?.title) || (
<Trans>Please wait...</Trans>
)}
</h2>
</span>
</div>
<div className="dialog-content">
<div className="form-content">
<label>
<Trans>Take a deep breath and enjoy being in the present moment...</Trans>
</label>
<div className="progress-bar-wrapper">
<span className="progress-bar">
<span className={`progress ${progress === 100 ? "completed" : ""}`} style={progressBarStyle} />
</span>
{!this.isInfiniteProgressMode() && (
<div className="progress-details">
<span className="progress-step-label">
{this.decodedHtmlCharacters(this.props.progressContext.progressDialogProps?.message) || (
<Trans>Please wait...</Trans>
)}
</span>
<span className="progress-percent">{progress}%</span>
</div>
)}
</div>
</div>
<div className="submit-wrapper clearfix">
<button type="submit" className="disabled processing">
Submit
<SpinnerSVG />
</button>
</div>
</div>
</div>
</div>
);
}
}
DisplayProgress.propTypes = {
progressContext: PropTypes.any, // The progress context
};
export default withProgress(withTranslation("common")(DisplayProgress));