UNPKG

passbolt-styleguide

Version:

Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.

287 lines (264 loc) 9.7 kB
/** * 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 2.13.0 */ import React from "react"; import PropTypes from "prop-types"; import { withAppContext } from "../../../../shared/context/AppContext/AppContext"; import { withRouter } from "react-router-dom"; import { ResourceWorkspaceFilterTypes, withResourceWorkspace } from "../../../contexts/ResourceWorkspaceContext"; import { Trans, withTranslation } from "react-i18next"; import { formatDateTimeAgo } from "../../../../shared/utils/dateUtils"; import CaretDownSVG from "../../../../img/svg/caret_down.svg"; import CaretRightSVG from "../../../../img/svg/caret_right.svg"; import FolderSVG from "../../../../img/svg/folder.svg"; import ShareFolderSVG from "../../../../img/svg/share_folder.svg"; import TooltipPortal from "../../Common/Tooltip/TooltipPortal"; import CabinetSVG from "../../../../img/svg/cabinet.svg"; class DisplayResourceFolderDetailsInformation extends React.Component { /** * Constructor * @param {Object} props */ constructor(props) { super(props); this.state = this.getDefaultState(); this.bindCallbacks(); } /** * Get default state * @returns {*} */ getDefaultState() { return { open: true, creator: null, // the data of the folder creator modifier: null, // the data of the folder modifier }; } /** * Bind callbacks methods */ bindCallbacks() { this.handleFolderParentClickEvent = this.handleFolderParentClickEvent.bind(this); this.handleTitleClickEvent = this.handleTitleClickEvent.bind(this); } componentDidMount() { if (this.state.open) { this.loadUserInformation(); } } /** * Whenever the component has updated in terms of props * @param {object} prevProps The previous componentDidUpdate props */ componentDidUpdate(prevProps) { this.handleFolderChange(prevProps.resourceWorkspaceContext.details.folder); } /** * Check if the folder has changed and fetch * @param {object} previousFolder The previously selected folder */ handleFolderChange(previousFolder) { const hasModifierOrCreatorChanged = this.folder.created_by !== previousFolder.created_by || this.folder.modified_by !== previousFolder.modified_by; if (hasModifierOrCreatorChanged && this.state.open) { this.loadUserInformation(); } } /** * Loads the information about the creator and the modifier of the current selected folder. * @returns {Promise<void>} */ async loadUserInformation() { const folderInformation = await this.props.context.port.request("passbolt.folders.find-details", this.folder.id); this.setState({ creator: folderInformation?.creator, modifier: folderInformation?.modifier, }); } /** * Handle when the user selects the folder parent. */ handleFolderParentClickEvent() { if (this.folder.folder_parent_id) { // Case of specific folder const folderParent = this.props.context.folders.find((item) => item.id === this.folder.folder_parent_id); this.props.history.push(`/app/folders/view/${folderParent.id}`); } else { // Case of root folder const filter = { type: ResourceWorkspaceFilterTypes.ROOT_FOLDER }; this.props.history.push(`/app/passwords`, { filter }); } } /** * Handle when the user selects the folder parent. */ handleTitleClickEvent() { const open = !this.state.open; this.setState({ open }); } /** * Returns the current detailed folder */ get folder() { return this.props.resourceWorkspaceContext.details.folder; } /** * Get the folder name. * @param {string} folderId The folder id * @returns {string} */ getFolderName(folderParentId) { if (folderParentId === null) { return this.props.t("My workspace"); } if (this.props.context.folders) { const folder = this.props.context.folders.find((item) => item.id === folderParentId); if (folder) { return folder.name; } } return ""; } /** * Check if folder parent is shared * @returns {boolean} */ isFolderParentShared() { const isShared = false; if (this.folder.folder_parent_id !== null && this.props.context.folders) { const folder = this.props.context.folders.find((item) => item.id === this.folder.folder_parent_id); if (folder) { return !folder.personal; } } return isShared; } /** * Render the tooltip folders structure. * @param {array<FolderEntity>} folderStructure The folders structure. * @render {JSX} */ renderTooltipFolderStructure(folderStructure) { if (folderStructure.length === 0) { return ( <span> <Trans>My workspace</Trans> </span> ); } return folderStructure?.map((folder, index) => ( <div key={folder.id} className="folder-level" style={{ marginLeft: `${5 * index}px` }}> {folder.folder_parent_id !== null && <span className="caret"></span>} <span>{folder.name}</span> </div> )); } /** * Render the component * @returns {JSX} */ render() { const creatorUsername = this.state.creator?.username || ""; const modifierUsername = this.state.modifier?.username || ""; const createdDateTimeAgo = formatDateTimeAgo(this.folder.created, this.props.t, this.props.context.locale); const modifiedDateTimeAgo = formatDateTimeAgo(this.folder.modified, this.props.t, this.props.context.locale); const folderStructure = this.props.context.getHierarchyFolderCache(this.folder.folder_parent_id); return ( <div className={`detailed-information accordion sidebar-section ${this.state.open ? "" : "closed"}`}> <div className="accordion-header"> <h4> <button className="link no-border" type="button" onClick={this.handleTitleClickEvent}> <span className="accordion-title"> <Trans>Information</Trans> </span> {this.state.open ? <CaretDownSVG /> : <CaretRightSVG />} </button> </h4> </div> {this.state.open && ( <div className="accordion-content"> <div className="information-label"> <span className="username label"> <Trans>Name</Trans> </span> <span className="created label"> <Trans>Created</Trans> </span> <span className="created-by label"> <Trans>Created by</Trans> </span> <span className="modified label"> <Trans>Modified</Trans> </span> <span className="modified-by label"> <Trans>Modified by</Trans> </span> <span className="location label"> <Trans>Location</Trans> </span> </div> <div className="information-value"> <span className="username value">{this.folder.name}</span> <span className="created value" title={this.folder.created}> {createdDateTimeAgo} </span> <span className="created-by value">{creatorUsername}</span> <span className="modified value" title={this.folder.modified}> {modifiedDateTimeAgo} </span> <span className="modified-by value">{modifierUsername}</span> <span className="location value"> <TooltipPortal message={this.renderTooltipFolderStructure(folderStructure)}> <button type="button" onClick={this.handleFolderParentClickEvent} disabled={!this.props.context.folders} className="no-border" > {this.folder.folder_parent_id === null && ( <> <CabinetSVG /> <Trans>My workspace</Trans> </> )} {this.folder.folder_parent_id !== null && ( <> {this.isFolderParentShared() ? <ShareFolderSVG /> : <FolderSVG />} {folderStructure.map((folder) => ( <React.Fragment key={folder.id}> {folder.folder_parent_id !== null && <span className="caret"></span>} <span>{folder.name}</span> </React.Fragment> ))} </> )} </button> </TooltipPortal> </span> </div> </div> )} </div> ); } } DisplayResourceFolderDetailsInformation.propTypes = { context: PropTypes.any, // The application context history: PropTypes.object, resourceWorkspaceContext: PropTypes.object, t: PropTypes.func, // The translation function }; export default withAppContext( withRouter(withResourceWorkspace(withTranslation("common")(DisplayResourceFolderDetailsInformation))), );