passbolt-styleguide
Version:
Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.
326 lines (303 loc) • 12.5 kB
JavaScript
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) 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) Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 3.2.0
*/
import React from "react";
import PropTypes from "prop-types";
import {withAppContext} from "../../../contexts/AppContext";
import {DateTime} from "luxon";
import {withAdministrationWorkspace} from "../../../contexts/AdministrationWorkspaceContext";
import {Trans, withTranslation} from "react-i18next";
import {withDialog} from "../../../../react-extension/contexts/DialogContext";
import {withNavigationContext} from "../../../contexts/NavigationContext";
import Icon from "../../../../shared/components/Icons/Icon";
import AnimatedFeedback from "../../../../shared/components/Icons/AnimatedFeedback";
import SubscriptionActionService from '../../../../shared/services/actions/subscription/SubscriptionActionService';
import DisplayAdministrationSubscriptionActions from "../DisplayAdministrationWorkspaceActions/DisplayAdministrationSubscriptionActions/DisplayAdministrationSubscriptionActions";
import {withAdminSubscription} from "../../../contexts/Administration/AdministrationSubscription/AdministrationSubscription";
/**
* This component allows to display the subscription key for the administration
*/
class DisplaySubscriptionKey extends React.Component {
/**
* Constructor
* @param {Object} props
*/
constructor(props) {
super(props);
this.state = this.defaultState;
this.bindCallbacks();
this.subscriptionActionService = SubscriptionActionService.getInstance(this.props);
}
/**
* Get default state
* @returns {*}
*/
get defaultState() {
return {
// active users
activeUsers: null // The number of active users
};
}
/**
* ComponentDidMount
* Invoked immediately after component is inserted into the tree
* @return {void}
*/
async componentDidMount() {
this.props.administrationWorkspaceContext.setDisplayAdministrationWorkspaceAction(DisplayAdministrationSubscriptionActions);
this.findActiveUsers();
await this.findSubscriptionKey();
}
/**
* componentWillUnmount
* Use to clear the data from the form in case the user put something that needs to be cleared.
*/
componentWillUnmount() {
this.props.administrationWorkspaceContext.resetDisplayAdministrationWorkspaceAction();
this.props.adminSubcriptionContext.clearContext();
SubscriptionActionService.killInstance();
this.mfaFormService = null;
}
/**
* Bind callbacks methods
*/
bindCallbacks() {
this.handleRenewKey = this.handleRenewKey.bind(this);
this.handleUpdateKey = this.handleUpdateKey.bind(this);
}
/**
* fetch the active users
*/
async findActiveUsers() {
const activeUsers = await this.props.adminSubcriptionContext.getActiveUsers();
this.setState({activeUsers});
}
/**
* fetch the subscription key
*/
async findSubscriptionKey() {
this.props.adminSubcriptionContext.findSubscriptionKey();
}
/**
* Handle renew key click event
*/
handleRenewKey() {
const subscription = this.props.adminSubcriptionContext.getSubscription();
if (this.hasLimitUsersExceeded()) {
this.props.navigationContext.onGoToNewTab(`https://www.passbolt.com/subscription/ee/update/qty?subscription_id=${subscription.subscriptionId}&customer_id=${subscription.customerId}`);
} else if (this.hasSubscriptionKeyExpired() || this.hasSubscriptionKeyGoingToExpire()) {
this.props.navigationContext.onGoToNewTab(`https://www.passbolt.com/subscription/ee/update/renew?subscription_id=${subscription.subscriptionId}&customer_id=${subscription.customerId}`);
}
}
/**
* Handle update key click event
*/
handleUpdateKey() {
this.subscriptionActionService.editSubscription();
}
/**
* Has subscription key expired
* @returns {boolean}
*/
hasSubscriptionKeyExpired() {
return DateTime.fromISO(this.props.adminSubcriptionContext.getSubscription().expiry) < DateTime.now();
}
/**
* Has subscription key going to expire
* @returns {boolean}
*/
hasSubscriptionKeyGoingToExpire() {
return DateTime.fromISO(this.props.adminSubcriptionContext.getSubscription().expiry) < DateTime.now().plus({days: 30}) && !this.hasSubscriptionKeyExpired();
}
/**
* Has no subscription key
* @returns {boolean}
*/
hasSubscriptionKey() {
return Boolean(this.props.adminSubcriptionContext.getSubscription().data);
}
/**
* Has limit of users exceeded
* @returns {boolean}
*/
hasLimitUsersExceeded() {
const subscription = this.props.adminSubcriptionContext.getSubscription();
return subscription.users < this.state.activeUsers;
}
/**
* Has subscription to renew
* @returns {boolean}
*/
hasSubscriptionToRenew() {
return this.hasInvalidSubscription() || this.hasSubscriptionKeyGoingToExpire();
}
/**
* Has valid subscription
* @returns {boolean}
*/
hasValidSubscription() {
return this.hasSubscriptionKey() && !this.hasLimitUsersExceeded()
&& !this.hasSubscriptionKeyExpired();
}
/**
* Has invalid subscription
* @returns {boolean}
*/
hasInvalidSubscription() {
return !this.hasSubscriptionKey() || this.hasLimitUsersExceeded() || this.hasSubscriptionKeyExpired();
}
/**
* Format a date.
* @string {string} date The date to format
* @return {string}
*/
formatDate(date) {
try {
return DateTime.fromISO(date).setLocale(this.props.context.locale).toLocaleString(DateTime.DATE_SHORT);
} catch (error) {
return "";
}
}
/**
* Format date in time ago
* @param {string} date The date to format
* @return {string}
*/
formatDateTimeAgo(date) {
const dateTime = DateTime.fromISO(date);
const duration = dateTime.diffNow().toMillis();
return duration > -1000 && duration < 0 ? this.translate('Just now') : dateTime.toRelative({locale: this.props.context.locale});
}
/**
* Get the translate function
* @returns {function(...[*]=)}
*/
get translate() {
return this.props.t;
}
/**
* Render the component
* @returns {JSX}
*/
render() {
const subscription = this.props.adminSubcriptionContext.getSubscription();
const isProcessing = this.props.adminSubcriptionContext.isProcessing();
return (
<div className="row">
{!isProcessing &&
<div className="subscription-key col8 main-column">
<h3><Trans>Subscription key details</Trans></h3>
<div className="feedback-card">
{this.hasValidSubscription() && !this.hasSubscriptionKeyGoingToExpire() &&
<AnimatedFeedback name="success" />
}
{this.hasInvalidSubscription() &&
<AnimatedFeedback name="error" />
}
{this.hasValidSubscription() && this.hasSubscriptionKeyGoingToExpire() &&
<AnimatedFeedback name="warning" />
}
<div className="subscription-information">
{!this.hasSubscriptionKey() &&
<>
<h4 className="no-border"><Trans>Your subscription key is either missing or not valid.</Trans></h4>
<p><Trans>Sorry your subscription is either missing or not readable.</Trans><br/>
<Trans>Update the subscription key and try again.</Trans> <Trans>If this does not work get in touch with support.</Trans>
</p>
</>
}
{this.hasValidSubscription() && this.hasSubscriptionKeyGoingToExpire() &&
<h4 className="no-border"><Trans>Your subscription key is going to expire.</Trans></h4>
}
{this.hasSubscriptionKey() && this.hasInvalidSubscription() &&
<h4 className="no-border"><Trans>Your subscription key is not valid.</Trans></h4>
}
{this.hasValidSubscription() && !this.hasSubscriptionKeyGoingToExpire() &&
<h4 className="no-border"><Trans>Your subscription key is valid and up to date!</Trans></h4>
}
{this.hasSubscriptionKey() &&
<ul>
<li className="customer-id">
<span className="label"><Trans>Customer id:</Trans></span>
<span className="value">{subscription.customerId}</span>
</li>
<li className="subscription-id">
<span className="label"><Trans>Subscription id:</Trans></span>
<span className="value">{subscription.subscriptionId}</span>
</li>
<li className="email">
<span className="label"><Trans>Email:</Trans></span>
<span className="value">{subscription.email}</span>
</li>
<li className="users">
<span
className={`label ${this.hasLimitUsersExceeded() ? "error" : ""}`}><Trans>Users limit:</Trans></span>
<span
className={`value ${this.hasLimitUsersExceeded() ? "error" : ""}`}>{subscription.users} (<Trans>currently:</Trans> {this.state.activeUsers})</span>
</li>
<li className="created">
<span className="label"><Trans>Valid from:</Trans></span>
<span className="value">{this.formatDate(subscription.created)}</span>
</li>
<li className="expiry">
<span
className={`label ${this.hasSubscriptionKeyExpired() ? "error" : ""} ${this.hasSubscriptionKeyGoingToExpire() ? "warning" : ""}`}><Trans>Expires on:</Trans></span>
<span
className={`value ${this.hasSubscriptionKeyExpired() ? "error" : ""} ${this.hasSubscriptionKeyGoingToExpire() ? "warning" : ""}`}>{this.formatDate(subscription.expiry)} ({`${this.hasSubscriptionKeyExpired() ? this.translate("expired ") : ""}${this.formatDateTimeAgo(subscription.expiry)}`})</span>
</li>
</ul>
}
{this.hasSubscriptionToRenew() &&
<div className="actions-wrapper">
{this.hasSubscriptionKey() &&
<button className="button primary" type="button" onClick={this.handleRenewKey}>
<Trans>Renew key</Trans>
</button>
}
{!this.hasSubscriptionKey() &&
<button className="button primary" type="button" onClick={this.handleUpdateKey}>
<Trans>Update key</Trans>
</button>
}
<a target="_blank" rel="noopener noreferrer" href="https://www.passbolt.com/contact"><Trans>or, contact us</Trans></a>
</div>
}
</div>
</div>
</div>
}
{!isProcessing &&
<div className="col4 last">
<div className="sidebar-help">
<h3><Trans>Need help?</Trans></h3>
<p><Trans>For any change or question related to your passbolt subscription, kindly contact our sales team.</Trans></p>
<a className="button" target="_blank" rel="noopener noreferrer" href="https://www.passbolt.com/contact">
<Icon name="envelope"/>
<span><Trans>Contact Sales</Trans></span>
</a>
</div>
</div>
}
</div>
);
}
}
DisplaySubscriptionKey.propTypes = {
context: PropTypes.any, // The application context
navigationContext: PropTypes.any, // The application navigation context
administrationWorkspaceContext: PropTypes.object, // The administration workspace context
adminSubcriptionContext: PropTypes.object, // The administration subscription context
dialogContext: PropTypes.any, // The dialog congtext
t: PropTypes.func,
};
export default withAppContext(withNavigationContext(withAdminSubscription(withAdministrationWorkspace(withDialog(withTranslation('common')(DisplaySubscriptionKey))))));