passbolt-styleguide
Version:
Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.
440 lines (402 loc) • 14 kB
JavaScript
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) 2022 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) 2022 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.8.3
*/
import React from "react";
import PropTypes from "prop-types";
import { withAppContext } from "../../../../shared/context/AppContext/AppContext";
import SelfRegistrationService from "../../../../shared/services/api/selfRegistration/selfRegistrationService";
import SelfRegistrationDomainsViewModel from "../../../../shared/models/selfRegistration/SelfRegistrationDomainsViewModel";
import MapObject from "../../../lib/Map/MapObject";
import SelfRegistrationDto from "../../../../shared/models/selfRegistration/SelfRegistrationDto";
import SelfRegistrationFormService from "../../../../shared/services/forms/selfRegistration/SelfRegistrationFormService";
import ConfirmSaveSelfRegistrationSettings from "../../../components/Administration/DisplaySelfRegistrationAdministration/ConfirmSaveSelfRegistrationSettings/ConfirmSaveSelfRegistrationSettings";
import NotifyError from "../../../components/Common/Error/NotifyError/NotifyError";
import { withActionFeedback } from "../../ActionFeedbackContext";
import { withDialog } from "../../DialogContext";
import { withTranslation } from "react-i18next";
import ConfirmDeletionSelfRegistrationSettings from "../../../components/Administration/DisplaySelfRegistrationAdministration/ConfirmDeletionSelfRegistrationSettings/ConfirmDeletionSelfRegistrationSettings";
/**
* The Administration Self registration Context
* @type {React.Context<Object>}
*/
export const AdminSelfRegistrationContext = React.createContext({
getCurrentSettings: () => {}, // Returns settings saved
getAllowedDomains: () => {}, // Returns allowed domains for UI changes
setAllowedDomains: () => {}, // Returns allowed domains for UI changes
hasSettingsChanges: () => {}, // Check if the policy has changes
setDomains: () => {}, // change domains
findSettings: () => {}, // Find the current self registraiton settings and store it in the state
setProcessing: () => {}, //Update processing object
isProcessing: () => {}, // returns true if a process is running and the UI must be disabled
clearContext: () => {}, // put the data to its default state value
isSubmitted: () => {}, // returns the value submitted
setSubmitted: () => {}, // Set the submitted variable
setErrors: () => {}, // Set errors to object object
getErrors: () => {}, // Return current errors
setError: () => {}, // Init errors object message
save: () => {}, // Save settings,
delete: () => {}, // Delete settings,
shouldFocus: () => {}, // Return the focus object,
setFocus: () => {}, // Set the focus object,
isSaved: () => {}, // return saved value
setSaved: () => {}, // init saved value
validateForm: () => {}, // Validate the form
});
/**
* The Administration self registration context provider
*/
export class AdminSelfRegistrationContextProvider extends React.Component {
/**
* Default constructor
* @param props The component props
*/
constructor(props) {
super(props);
this.state = this.defaultState;
const apiClientOptions = props.context.getApiClientOptions();
this.selfRegistrationService = new SelfRegistrationService(apiClientOptions);
this.selfRegistrationFormService = new SelfRegistrationFormService(this.props.t);
}
/**
* Returns the default component state
*/
get defaultState() {
return {
errors: new Map(), // The error map object
submitted: false, // The informations about the form state
currentSettings: null, // The current settings
focus: false, // return request to focus to input
saved: false, // return request to inform about a saved
domains: new SelfRegistrationDomainsViewModel(), // Change done to the allowed domains object
processing: true, // Context is processing data
getCurrentSettings: this.getCurrentSettings.bind(this), // Returns settings saved
getAllowedDomains: this.getAllowedDomains.bind(this), // Returns allowed domains for UI changes
setAllowedDomains: this.setAllowedDomains.bind(this), // Returns allowed domains for UI changes
setDomains: this.setDomains.bind(this), // change domains
findSettings: this.findSettings.bind(this), // Find the current self registraiton settings and store it in the state
hasSettingsChanges: this.hasSettingsChanges.bind(this), // Check if setting has changes
isProcessing: this.isProcessing.bind(this), // returns true if a process is running and the UI must be disabled
setProcessing: this.setProcessing.bind(this),
clearContext: this.clearContext.bind(this), // put the data to its default state value
isSubmitted: this.isSubmitted.bind(this), // returns the value submitted
setSubmitted: this.setSubmitted.bind(this), // Set the submitted variable
getErrors: this.getErrors.bind(this), // Return current errors
setError: this.setError.bind(this), // Set an error to object object
setErrors: this.setErrors.bind(this), // Set errors to object object
save: this.save.bind(this), // Save the policy changes
shouldFocus: this.shouldFocus.bind(this), // Return the focus object,
setFocus: this.setFocus.bind(this), // Set the focus object
isSaved: this.isSaved.bind(this), // return saved value
setSaved: this.setSaved.bind(this), // init saved value
deleteSettings: this.deleteSettings.bind(this), // Delete settings,
validateForm: this.validateForm.bind(this), // Validate the form
};
}
/**
* Find the self registration settings
* @return {Promise<SelfRegistrationDomainsViewModel>}
*/
async findSettings(callback = () => {}) {
this.setProcessing(true);
const result = await this.selfRegistrationService.find();
//Init saved setting
this.setState({ currentSettings: result });
const domains = new SelfRegistrationDomainsViewModel(result);
//Init allowed domains which will interact with UI
this.setDomains(domains, callback);
this.setProcessing(false);
return domains;
}
/**
* Returns the setting actually saved inside DB
* @returns {object}
*/
getCurrentSettings() {
return this.state.currentSettings;
}
/**
* Returns the allowed domains settings that have been fetch previously.
* @returns {object}
*/
getAllowedDomains() {
return this.state.domains.allowedDomains;
}
/**
* Handle settings changes.
* @params {ReactEvent} The react event
* @returns {void}
*/
setAllowedDomains(key, value, callback = () => {}) {
this.setState((prevState) => {
const allowedDomains = MapObject.clone(prevState.domains.allowedDomains);
allowedDomains.set(key, value);
return { domains: { allowedDomains } };
}, callback);
}
/**
* Handle domains changes.
* @params {ReactEvent} The react event
* @returns {void}
*/
setDomains(domains, callback = () => {}) {
this.setState({ domains }, callback);
}
/**
* Returns true when the data is under processing
* @returns {boolean}
*
*/
isProcessing() {
return this.state.processing;
}
/**
* Handle processing change.
* @params {Boolean} processing value
* @returns {void}
*/
setProcessing(processing) {
this.setState({ processing });
}
/**
* return true if the form has been submitted
* @returns {Boolean}
*/
isSubmitted() {
return this.state.submitted;
}
/**
* change value for isSubmitted
* @params {Boolean}
* @returns {Boolean}
*/
setSubmitted(submitted) {
this.setState({ submitted });
this.setFocus(submitted);
}
/**
* return the errors object
*/
getErrors() {
return this.state.errors;
}
/**
* return the focus object
*/
shouldFocus() {
return this.state.focus;
}
/**
* change value for isSubmitted
* @params {Boolean}
* @returns {Boolean}
*/
setFocus(focus) {
this.setState({ focus });
}
/**
* set an error to object
*/
setError(key, value) {
const errors = MapObject.clone(this.state.errors);
errors.set(key, value);
this.setState({ errors });
}
/**
* set errors to object
*/
setErrors(errors) {
this.setState({ errors });
}
/**
* Check if there are changes to apply
* @returns {Boolean}
*/
hasSettingsChanges() {
// we compare the domains from the server vs the UI
const savedDomains = this.state.currentSettings?.data?.allowed_domains || [];
const uiDomains = MapObject.listValues(this.state.domains.allowedDomains);
return JSON.stringify(savedDomains) !== JSON.stringify(uiDomains);
}
/**
* Puts the state to its default in order to avoid keeping the data users didn't want to save.
*/
clearContext() {
const { currentSettings, domains, processing } = this.defaultState;
this.setState({
currentSettings,
domains,
processing,
});
}
/**
* Whenever the save has been requested
*/
save() {
this.setSubmitted(true);
const isValid = this.validateForm();
if (!isValid) {
return;
}
if (this.hasSettingsChanges() && this.getAllowedDomains().size === 0) {
this.displayConfirmDeletionDialog();
} else {
this.displayConfirmSummaryDialog();
}
}
/**
* validate the form
* @returns {boolean}
*/
validateForm() {
const errors = this.selfRegistrationFormService.validate(this.state.getAllowedDomains());
this.state.setErrors(errors);
return errors.size === 0;
}
/**
* Handle save operation error.
* @param {object} error The returned error
*/
async handleSubmitError(error) {
if (error.name !== "UserAbortsOperationError") {
// Unexpected error occurred.
console.error(error);
await this.handleError(error);
}
}
/**
* Whenever the submit request is done
*/
async saveSettings() {
try {
this.setProcessing(true);
const newSettings = new SelfRegistrationDto(this.state.domains, this.state.currentSettings);
await this.selfRegistrationService.save(newSettings);
await this.findSettings(() => this.setSaved(true));
await this.props.actionFeedbackContext.displaySuccess(
this.props.t("The self registration settings for the organization were updated."),
);
} catch (error) {
this.handleSubmitError(error);
} finally {
this.setProcessing(false);
this.setSubmitted(false);
}
}
/**
* handle error to display the error dialog
* @param error
*/
async handleError(error) {
this.handleCloseDialog();
const errorDialogProps = {
error: error,
};
this.props.dialogContext.open(NotifyError, errorDialogProps);
}
/**
* Handle close dialog
*/
handleCloseDialog() {
this.props.dialogContext.close();
}
/**
* Display the confirmation summary dialog
* @returns {Promise<void>}
*/
displayConfirmSummaryDialog() {
this.props.dialogContext.open(ConfirmSaveSelfRegistrationSettings, {
domains: this.getAllowedDomains(),
onSubmit: () => this.saveSettings(),
onClose: () => this.handleCloseDialog(),
});
}
/**
* Display the confirmation dialog for deletion seytings
* @returns {Promise<void>}
*/
displayConfirmDeletionDialog() {
this.props.dialogContext.open(ConfirmDeletionSelfRegistrationSettings, {
onSubmit: () => this.deleteSettings(),
onClose: () => this.handleCloseDialog(),
});
}
/**
* Whenever the delete has been requested
*/
async deleteSettings() {
try {
this.setProcessing(true);
await this.selfRegistrationService.delete(this.state.currentSettings.id);
await this.findSettings();
await this.props.actionFeedbackContext.displaySuccess(
this.props.t("The self registration settings for the organization were updated."),
);
} catch (error) {
this.handleSubmitError(error);
} finally {
this.setProcessing(false);
this.setSubmitted(false);
}
}
/**
* return the saved state
*/
isSaved() {
return this.state.saved;
}
/**
* Set saved state
* @Param {Boolean}
*/
setSaved(saved) {
return this.setState({ saved });
}
/**
* Render the component
* @returns {JSX}
*/
render() {
return (
<AdminSelfRegistrationContext.Provider value={this.state}>
{this.props.children}
</AdminSelfRegistrationContext.Provider>
);
}
}
AdminSelfRegistrationContextProvider.propTypes = {
context: PropTypes.any, // The application context
children: PropTypes.any, // The children components
t: PropTypes.any, // The translate context
dialogContext: PropTypes.any, // The dialog context
actionFeedbackContext: PropTypes.object, // The action feedback context
};
export default withAppContext(
withDialog(withActionFeedback(withTranslation("common")(AdminSelfRegistrationContextProvider))),
);
/**
* Resource Workspace Context Consumer HOC
* @param WrappedComponent
*/
export function withAdminSelfRegistration(WrappedComponent) {
return class WithAdminSelfRegistration extends React.Component {
render() {
return (
<AdminSelfRegistrationContext.Consumer>
{(adminSelfRegistrationContext) => (
<WrappedComponent adminSelfRegistrationContext={adminSelfRegistrationContext} {...this.props} />
)}
</AdminSelfRegistrationContext.Consumer>
);
}
};
}