UNPKG

passbolt-styleguide

Version:

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

293 lines (270 loc) 8.84 kB
/** * 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.11.0 */ import { use } from "i18next"; import { initReactI18next } from "react-i18next"; import enTranslations from "../../locales/en-UK/common.json"; import { fireEvent, render, waitFor } from "@testing-library/react"; import React from "react"; import AppContext from "../../shared/context/AppContext/AppContext"; import { Router, NavLink, Route, Switch } from "react-router-dom"; import { createMemoryHistory } from "history"; import UserWorkspaceContextProvider, { UserWorkspaceFilterTypes, UserWorkspaceContext } from "./UserWorkspaceContext"; /** * The UserWorkspaceContextPage component represented as a page */ export default class UserWorkspaceContextPage { /** * Default constructor * @param appContext An app context * @param props Props to attach */ constructor(appContext, props) { this.context = appContext; this.props = props; this.configureTranslation(); this.setup(appContext, props); } /* * Configuring i18n avoid some warning showing in the console during the test. * A better choice would be to use MockTranslationProvider. But somehow, it breaks some unit tests. * The reason seams that it influences in an unknown way the value of this.userWorkspaceContext.filter.type * by making it equals to ALL instead of the desired value when the check is done. */ configureTranslation() { use(initReactI18next) // init i18next, for all options read: https://www.i18next.com/overview/configuration-options .init({ lng: "en-UK", resources: { "en-UK": { common: enTranslations, }, }, react: { useSuspense: false, }, fallbackLng: false, ns: ["common"], defaultNS: "common", keySeparator: false, // don't use the dot for separator of nested json object nsSeparator: false, // allowed ':' in key to avoid namespace separator debug: false, }); } /** * Returns the contextual filter */ get filter() { return this.userWorkspaceContext.filter; } /** * Returns the contextual details */ get details() { return this.userWorkspaceContext.details; } /** * Returns the lock on details */ get lockDisplayDetail() { return this.userWorkspaceContext.details.locked; } /** * Returns the filtered users */ get filteredUsers() { return this.userWorkspaceContext.filteredUsers; } /** * Returns the contextual selected resources */ get selectedUsers() { return this.userWorkspaceContext.selectedUsers; } /** * Go to the given link identified by CSS selector and click on it * @returns {Promise<void>} * @ linkCssSelector The CSS link selector */ async goToLink(linkCssSelector) { const oldFilter = this.filter; const element = this._page.container.querySelector(linkCssSelector); const leftClick = { button: 0 }; fireEvent.click(element, leftClick); await waitFor(() => { if (oldFilter == this.filter) { throw new Error("Context didn't change yet."); } }); } /** * Go to the All Users search filter route */ async goToAllUsers() { this.setup(this.context, this.props); await this.goToLink(".all"); } /** * Go to the Recently Modified search filter route */ async goToRecentlyModified() { await this.goToLink(".recently-modified"); } /** * Go to the Recently Modified search filter route */ async goToSuspendedUsers() { await this.goToLink(".suspended-users"); } /** * Go to the Attention Required Account Recovery search filter route */ async goToAccountRecoveryRequestUsers() { await this.goToLink(".account-recovery-request-users"); } /** * Go to the Attention Required Missing metadata keys search filter route */ async goToMissingMetadataKeysUsers() { await this.goToLink(".missing-metadata-keys-users"); } /** * Go to the Text search filter route * @param text A specific text search filter */ async goToText(text) { this.setup(this.context, this.props, { text }); await this.goToLink(".text"); } /** * Go to the Group search filter route * @param group A specific group search filter */ async goToGroup(group) { this.setup(this.context, this.props, { group }); await this.goToLink(".group"); } /** * Select the given user * @param resource A specific resource */ async select(user) { const currentLength = this.selectedUsers.length; await this.userWorkspaceContext.onUserSelected.single(user); await waitFor(() => { if (this.selectedUsers.length === currentLength) { throw new Error("Selection state not updated yet"); } }); } /** * Toggle the display lock on details */ async toggleLockDetails() { await this.userWorkspaceContext.onDetailsLocked(); await waitFor(() => {}); } /** * Update details of user or group * @param user A specific user * @pram group A group */ updateDetails({ user, group }) { this.userWorkspaceContext.details = { user, group, locked: true, }; } /** * Remove from the selected users those which are not present in regard of the current displayed list */ unselectUsersNotFiltered() { const matchId = (selectedUser) => (user) => user.id === selectedUser.id; const filtered = this.selectedUsers.filter((selectedUser) => this.filteredUsers.some(matchId(selectedUser))); if (filtered.length === 1) { this.userWorkspaceContext.onUserSelected.single(filtered[0]); } else { this.userWorkspaceContext.onUserSelected.none(); } } /** * Returns the rendering of the page * @param appContext a app context * @param text a specific text search filter * @param tag a specific tag search filter */ setup(appContext, props, args = {}) { this._page = render( <AppContext.Provider value={appContext}> <Router history={createMemoryHistory({ initialEntries: ["/app/groups/view/:selectedGroupId", "/app/users/view/:selectedResourceId", "/app/users"], })} > <Switch> <Route path={["/app/groups/view/:selectedGroupId", "/app/users/view/:selectedUserId", "/app/users"]}> <UserWorkspaceContextProvider {...props}> <UserWorkspaceContext.Consumer> {(UserWorkspaceContext) => { this.userWorkspaceContext = UserWorkspaceContext; return <></>; }} </UserWorkspaceContext.Consumer> </UserWorkspaceContextProvider> </Route> </Switch> <NavLink to="/app/users"> <a className="all"></a> </NavLink> <NavLink to={{ pathname: "/app/users", state: { filter: { type: UserWorkspaceFilterTypes.RECENTLY_MODIFIED } } }} > <a className="recently-modified"></a> </NavLink> <NavLink to={{ pathname: "/app/users", state: { filter: { type: UserWorkspaceFilterTypes.ACCOUNT_RECOVERY_REQUEST } }, }} > <a className="account-recovery-request-users"></a> </NavLink> <NavLink to={{ pathname: "/app/users", state: { filter: { type: UserWorkspaceFilterTypes.MISSING_METADATA_KEY } } }} > <a className="missing-metadata-keys-users"></a> </NavLink> <NavLink to={{ pathname: "/app/users", state: { filter: { type: UserWorkspaceFilterTypes.SUSPENDED_USER } } }} > <a className="suspended-users"></a> </NavLink> <NavLink to={{ pathname: "/app/users", state: { filter: { type: UserWorkspaceFilterTypes.TEXT, payload: args.text } }, }} > <a className="text"></a> </NavLink> <NavLink to={{ pathname: `/app/groups/view/${args.group ? args.group.id : ""}` }}> <a className="group"></a> </NavLink> x </Router> </AppContext.Provider>, ); } }