[MM-61966] "Browse or Create channel" menu on the right of team drop-down should use a11y supported menu (#29739)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c205398040
Коммит
1373c05931
@@ -94,11 +94,8 @@ describe('Leave an archived channel', () => {
|
||||
// # Archive the channel
|
||||
cy.uiArchiveChannel();
|
||||
|
||||
// # Click on add channel button
|
||||
cy.get('#SidebarContainer .AddChannelDropdown_dropdownButton').click();
|
||||
|
||||
// # Click on browse channels
|
||||
cy.get('#showMoreChannels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// # More channels modal opens
|
||||
cy.get('#browseChannelsModal').should('be.visible');
|
||||
@@ -141,11 +138,8 @@ describe('Leave an archived channel', () => {
|
||||
cy.uiArchiveChannel();
|
||||
});
|
||||
|
||||
// # Click on add channel button
|
||||
cy.get('#SidebarContainer .AddChannelDropdown_dropdownButton').click();
|
||||
|
||||
// # Click on browse channels
|
||||
cy.get('#showMoreChannels').click();
|
||||
// # Click on browse channels from menu
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// # More channels modal opens
|
||||
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||
@@ -194,11 +188,8 @@ describe('Leave an archived channel', () => {
|
||||
cy.url().should('include', `/${testTeam.name}/channels/${archivedPublicChannel1.name}`);
|
||||
});
|
||||
|
||||
// # Click on add channel button
|
||||
cy.get('#SidebarContainer .AddChannelDropdown_dropdownButton').click();
|
||||
|
||||
// # Click on browse channels
|
||||
cy.get('#showMoreChannels').click();
|
||||
// # Click on browse channels from menu
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// # More channels modal opens
|
||||
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||
@@ -248,11 +239,8 @@ describe('Leave an archived channel', () => {
|
||||
cy.get('#confirmModal').should('be.visible');
|
||||
cy.get('#confirmModalButton').click();
|
||||
|
||||
// # Click on add channel button
|
||||
cy.get('#SidebarContainer .AddChannelDropdown_dropdownButton').click();
|
||||
|
||||
// # Click on browse channels
|
||||
cy.get('#showMoreChannels').click();
|
||||
// # Click on browse channels from menu
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// # More channels modal opens
|
||||
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||
@@ -283,11 +271,8 @@ describe('Leave an archived channel', () => {
|
||||
cy.uiArchiveChannel();
|
||||
});
|
||||
|
||||
// # Click on add channel button
|
||||
cy.get('#SidebarContainer .AddChannelDropdown_dropdownButton').click();
|
||||
|
||||
// # Click on browse channels
|
||||
cy.get('#showMoreChannels').click();
|
||||
// # Click on browse channels from menu
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// # More channels modal opens and lands on all channels
|
||||
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||
@@ -318,11 +303,8 @@ describe('Leave an archived channel', () => {
|
||||
// # Archive the channel
|
||||
cy.uiArchiveChannel();
|
||||
|
||||
// # Click on add channel button
|
||||
cy.get('#SidebarContainer .AddChannelDropdown_dropdownButton').click();
|
||||
|
||||
// # Click on browse channels
|
||||
cy.get('#showMoreChannels').click();
|
||||
// # Click on browse channels from menu
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// # Modal should not contain the created channel
|
||||
cy.findByText(channelType.all).should('be.visible').click();
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('Channels', () => {
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
||||
// * Dropdown should be visible, defaulting to "All Channels"
|
||||
@@ -113,7 +113,7 @@ describe('Channels', () => {
|
||||
});
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
cy.get('#browseChannelsModal').should('be.visible');
|
||||
|
||||
@@ -167,7 +167,7 @@ describe('Channels', () => {
|
||||
});
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
||||
// * Verify that channel has zero members
|
||||
@@ -233,7 +233,7 @@ describe('Channels', () => {
|
||||
});
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Dropdown should be visible, defaulting to "All channels"
|
||||
cy.get('#menuWrapper').should('be.visible').within((el) => {
|
||||
@@ -288,7 +288,7 @@ function verifyBrowseChannelsModalWithArchivedSelection(isEnabled, testUser, tes
|
||||
|
||||
function verifyBrowseChannelsModal(isEnabled) {
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Verify that the browse channels modal is open and with or without option to view archived channels
|
||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('browse public channels', () => {
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Assert that the browse channel modal is visible
|
||||
cy.findByRole('dialog', {name: 'Browse Channels'}).should('be.visible').then(() => {
|
||||
@@ -108,7 +108,7 @@ describe('browse public channels', () => {
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Assert the moreChannelsModel is visible
|
||||
cy.findByRole('dialog', {name: 'Browse Channels'}).should('be.visible').then(() => {
|
||||
|
||||
@@ -53,7 +53,7 @@ describe('Channel routing', () => {
|
||||
|
||||
it('MM-T884_2 Creating new channel validates against two user IDs being used as channel name', () => {
|
||||
// # click on create public channel
|
||||
cy.uiBrowseOrCreateChannel('Create new channel').click();
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
// * Verify that the new channel modal is visible
|
||||
cy.get('#new-channel-modal').should('be.visible').within(() => {
|
||||
@@ -73,7 +73,7 @@ describe('Channel routing', () => {
|
||||
|
||||
it('MM-T884_3 Creating a new channel validates against gm-like names being used as channel name', () => {
|
||||
// # click on create public channel
|
||||
cy.uiBrowseOrCreateChannel('Create new channel').click();
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
// * Verify that the new channel modal is visible
|
||||
cy.findByRole('dialog', {name: 'Create a new channel'}).within(() => {
|
||||
|
||||
@@ -139,11 +139,8 @@ function createCategoryFromSidebarMenu() {
|
||||
// # Start with a new category
|
||||
const categoryName = `category-${getRandomId()}`;
|
||||
|
||||
// # Click on the sidebar menu dropdown
|
||||
cy.uiGetLHSAddChannelButton().click();
|
||||
|
||||
// # Click on create category link
|
||||
cy.findByText('Create new category').should('be.visible').click();
|
||||
// # Click on the sidebar menu dropdown and select Create Category
|
||||
cy.uiBrowseOrCreateChannel('Create new category');
|
||||
|
||||
// # Verify that Create Category modal has shown up.
|
||||
// # Wait for a while until the modal has fully loaded, especially during first-time access.
|
||||
|
||||
@@ -22,11 +22,8 @@ describe('Category sorting', () => {
|
||||
});
|
||||
|
||||
it('MM-T3916 Create Category character limit', () => {
|
||||
// # Click on the sidebar menu dropdown
|
||||
cy.uiGetLHSAddChannelButton().click();
|
||||
|
||||
// # Click on create category link
|
||||
cy.findByText('Create new category').should('be.visible').click();
|
||||
// # Click on the sidebar menu dropdown and select Create Category
|
||||
cy.uiBrowseOrCreateChannel('Create new category');
|
||||
|
||||
// # Add a name 26 characters in length e.g `abcdefghijklmnopqrstuvwxyz`
|
||||
cy.get('#editCategoryModal').should('be.visible').wait(TIMEOUTS.HALF_SEC).within(() => {
|
||||
|
||||
@@ -89,11 +89,8 @@ function createCategoryFromSidebarMenu() {
|
||||
// # Start with a new category
|
||||
const categoryName = `category-${getRandomId()}`;
|
||||
|
||||
// # Click on the sidebar menu dropdown
|
||||
cy.uiGetLHSAddChannelButton().click();
|
||||
|
||||
// # Click on create category link
|
||||
cy.findByText('Create new category').should('be.visible').click();
|
||||
// # Click on the sidebar menu dropdown and select Create Category
|
||||
cy.uiBrowseOrCreateChannel('Create new category');
|
||||
|
||||
// # Verify that Create Category modal has shown up.
|
||||
// # Wait for a while until the modal has fully loaded, especially during first-time access.
|
||||
|
||||
@@ -61,11 +61,8 @@ describe('Channel sidebar', () => {
|
||||
cy.get('#channelHeaderTitle').should('contain', 'Town Square');
|
||||
cy.url().should('include', `/${teamName}/channels/town-square`);
|
||||
|
||||
// # Click the New Channel Dropdown button
|
||||
cy.uiGetLHSAddChannelButton().should('be.visible').click();
|
||||
|
||||
// # Click the Browse channels dropdown item
|
||||
cy.get('.AddChannelDropdown .MenuItem:contains(Browse channels) button').should('be.visible').click();
|
||||
// # Click on the sidebar menu dropdown and select browse channels
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Verify that the more channels modal is visible
|
||||
cy.get('#browseChannelsModal').should('be.visible');
|
||||
|
||||
@@ -104,7 +104,7 @@ describe('Verify Accessibility Support in Modals & Dialogs', () => {
|
||||
cy.reload();
|
||||
|
||||
// * Verify the aria-label in more public channels button
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Verify the accessibility support in More Channels Dialog
|
||||
cy.findByRole('dialog', {name: 'Browse Channels'}).within(() => {
|
||||
@@ -140,7 +140,7 @@ describe('Verify Accessibility Support in Modals & Dialogs', () => {
|
||||
it.skip('MM-T1468 Accessibility Support in Add people to Channel Dialog screen', () => {
|
||||
// # Add atleast 5 users
|
||||
for (let i = 0; i < 5; i++) {
|
||||
cy.apiCreateUser().then(({user}) => { // eslint-disable-line
|
||||
cy.apiCreateUser().then(({user}) => { // eslint-disable-line
|
||||
cy.apiAddUserToTeam(testTeam.id, user.id);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ context('ldap', () => {
|
||||
|
||||
// # Go to team page to look for this channel in public channel directory
|
||||
cy.visit(`/${testTeam.name}`);
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Search private channel name and make sure it is still visible
|
||||
cy.get('#searchChannelsTextbox').type(testChannel.display_name);
|
||||
@@ -456,7 +456,7 @@ context('ldap', () => {
|
||||
cy.visit(`/${testTeam.name}/channels/off-topic`);
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Search public channel and ensure it appears in the list
|
||||
cy.get('#searchChannelsTextbox').type(publicChannel.display_name);
|
||||
@@ -473,7 +473,7 @@ context('ldap', () => {
|
||||
cy.visit(`/${testTeam.name}/channels/off-topic`);
|
||||
|
||||
// # Go to LHS and click 'Browse channels'
|
||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||
cy.uiBrowseOrCreateChannel('Browse channels');
|
||||
|
||||
// * Search private channel name and make sure it isn't there in public channel directory
|
||||
cy.get('#searchChannelsTextbox').type(publicChannel.display_name);
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('Team Permissions', () => {
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Click on create new channel at LHS
|
||||
cy.uiBrowseOrCreateChannel('Create new channel').click();
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
// * Verify that the create private channel is disabled
|
||||
cy.findByRole('dialog', {name: 'Create a new channel'}).find('#public-private-selector-button-P').should('have.class', 'disabled');
|
||||
|
||||
@@ -105,7 +105,7 @@ function verifyCreatePublicChannel(teamName, testUsers) {
|
||||
cy.visit(`/${teamName}/channels/town-square`);
|
||||
|
||||
// # Click on create new channel at LHS
|
||||
cy.uiBrowseOrCreateChannel('Create new channel').click();
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
cy.findByRole('dialog', {name: 'Create a new channel'}).within(() => {
|
||||
// * Verify if creating a public channel is disabled or not
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('Channel', () => {
|
||||
*/
|
||||
function verifyExistingChannelError(newChannelName, makePrivate = false) {
|
||||
// Click on '+' button for Public or Private Channel
|
||||
cy.uiBrowseOrCreateChannel('Create new channel').click();
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
if (makePrivate) {
|
||||
cy.get('#public-private-selector-button-P').click();
|
||||
|
||||
@@ -11,7 +11,7 @@ Cypress.Commands.add('uiCreateChannel', ({
|
||||
name = '',
|
||||
createBoard = '',
|
||||
}) => {
|
||||
cy.uiBrowseOrCreateChannel('Create new channel').click();
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
cy.get('#new-channel-modal').should('be.visible');
|
||||
if (isPrivate) {
|
||||
|
||||
@@ -13,11 +13,8 @@ import {getRandomId} from '../../utils';
|
||||
* cy.uiCreateSidebarCategory();
|
||||
*/
|
||||
function uiCreateSidebarCategory(categoryName: string = `category-${getRandomId()}`): ChainableT<any> {
|
||||
// # Click the New Category/Channel Dropdown button
|
||||
cy.uiGetLHSAddChannelButton().click();
|
||||
|
||||
// # Click the Create new category dropdown item
|
||||
cy.get('.AddChannelDropdown').should('be.visible').contains('.MenuItem', 'Create new category').click();
|
||||
// # Click on the sidebar menu dropdown and select Create Category
|
||||
cy.uiBrowseOrCreateChannel('Create new category');
|
||||
|
||||
cy.findByRole('dialog', {name: 'Rename Category'}).should('be.visible').within(() => {
|
||||
// # Fill in the category name and click 'Create'
|
||||
|
||||
@@ -31,8 +31,7 @@ Cypress.Commands.add('uiOpenTeamMenu', (item = '') => {
|
||||
});
|
||||
|
||||
Cypress.Commands.add('uiGetLHSAddChannelButton', () => {
|
||||
return cy.uiGetLHS().
|
||||
find('.AddChannelDropdown_dropdownButton');
|
||||
return cy.uiGetLHS().findByRole('button', {name: 'Browse or create channels'});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('uiGetLHSTeamMenu', () => {
|
||||
@@ -88,15 +87,16 @@ Cypress.Commands.add('uiGetLhsSection', (section) => {
|
||||
parent();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('uiBrowseOrCreateChannel', (item) => {
|
||||
cy.get('.AddChannelDropdown_dropdownButton').
|
||||
should('be.visible').
|
||||
click();
|
||||
cy.get('.dropdown-menu').should('be.visible');
|
||||
Cypress.Commands.add('uiBrowseOrCreateChannel', (menuitem) => {
|
||||
cy.uiGetLHSAddChannelButton().should('be.visible').click();
|
||||
|
||||
if (item) {
|
||||
cy.findByRole('menuitem', {name: item});
|
||||
}
|
||||
cy.get('#browserOrAddChannelMenu').
|
||||
should('exist').and('be.visible').
|
||||
within(() => {
|
||||
if (menuitem) {
|
||||
cy.findByText(menuitem).should('exist').click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('uiAddDirectMessage', () => {
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
|
||||
import {ActionTypes} from 'utils/constants';
|
||||
|
||||
export function setAddChannelDropdown(open: boolean) {
|
||||
return {
|
||||
type: ActionTypes.ADD_CHANNEL_DROPDOWN_TOGGLE,
|
||||
open,
|
||||
};
|
||||
}
|
||||
|
||||
export function setAddChannelCtaDropdown(open: boolean) {
|
||||
return {
|
||||
type: ActionTypes.ADD_CHANNEL_CTA_DROPDOWN_TOGGLE,
|
||||
|
||||
@@ -8,3 +8,4 @@ export {SubMenu} from './sub_menu';
|
||||
export {MenuItem as Item} from './menu_item';
|
||||
export type {FirstMenuItemProps} from './menu_item';
|
||||
export {MenuItemSeparator as Separator} from './menu_item_separator';
|
||||
export {openMenu, dismissMenu} from './menu_utils';
|
||||
|
||||
@@ -34,6 +34,8 @@ import {MenuContext, useMenuContextValue} from './menu_context';
|
||||
|
||||
import './menu.scss';
|
||||
|
||||
export const ELEMENT_ID_FOR_MENU_BACKDROP = 'backdropForMenuComponent';
|
||||
|
||||
const MENU_OPEN_ANIMATION_DURATION = 150;
|
||||
const MENU_CLOSE_ANIMATION_DURATION = 100;
|
||||
|
||||
@@ -56,8 +58,13 @@ type MenuButtonTooltipProps = {
|
||||
}
|
||||
|
||||
type MenuProps = {
|
||||
|
||||
/**
|
||||
* ID is mandatory as it is used in mobileWebview to open modal equivalent to menu
|
||||
*/
|
||||
id: string;
|
||||
'aria-label'?: string;
|
||||
'aria-labelledby'?: string;
|
||||
|
||||
/**
|
||||
* @warning Make the styling of your components such a way that they don't need this handler
|
||||
@@ -244,9 +251,10 @@ export function Menu(props: Props) {
|
||||
disableAutoFocusItem={disableAutoFocusItem} // This is not anti-pattern, see handleMenuButtonMouseDown
|
||||
MenuListProps={{
|
||||
id: props.menu.id,
|
||||
'aria-label': props.menu?.['aria-label'] ?? '',
|
||||
'aria-label': props.menu?.['aria-label'],
|
||||
'aria-labelledby': props.menu?.['aria-labelledby'],
|
||||
style: {
|
||||
width: props.menu.width || 'inherit',
|
||||
width: props.menu?.width,
|
||||
},
|
||||
}}
|
||||
TransitionProps={{
|
||||
@@ -257,6 +265,11 @@ export function Menu(props: Props) {
|
||||
exit: MENU_CLOSE_ANIMATION_DURATION,
|
||||
},
|
||||
}}
|
||||
slotProps={{
|
||||
backdrop: {
|
||||
id: ELEMENT_ID_FOR_MENU_BACKDROP,
|
||||
},
|
||||
}}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error This exists in source code of mui, but its types are missing
|
||||
onTransitionExited={providerValue.handleClosed}
|
||||
|
||||
29
webapp/channels/src/components/menu/menu_utils.ts
Обычный файл
29
webapp/channels/src/components/menu/menu_utils.ts
Обычный файл
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {ELEMENT_ID_FOR_MENU_BACKDROP} from './menu';
|
||||
|
||||
/**
|
||||
* Since the menu component requires actual interaction with the button
|
||||
* of the menu for opening the menus, we trigger it from here by clicking on the menu button
|
||||
*/
|
||||
export function openMenu(buttonId: string) {
|
||||
const menuButton = document.getElementById(buttonId);
|
||||
if (!menuButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
menuButton.click();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the menu by clicking on the backdrop
|
||||
*/
|
||||
export function dismissMenu() {
|
||||
const menuOverlay = document.getElementById(ELEMENT_ID_FOR_MENU_BACKDROP);
|
||||
if (!menuOverlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
menuOverlay.click();
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import {isShowOnboardingCompleteProfileTour} from 'selectors/views/onboarding_ta
|
||||
import {OnboardingTasksName, TaskNameMapToSteps} from './constants';
|
||||
import {useHandleOnBoardingTaskData} from './onboarding_tasks_manager';
|
||||
|
||||
const translate = {x: 0, y: -2};
|
||||
const translate = {x: 1, y: -9};
|
||||
|
||||
export const CompleteYourProfileTour = () => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -43,7 +43,7 @@ export const CompleteYourProfileTour = () => {
|
||||
</p>
|
||||
);
|
||||
|
||||
const overlayPunchOut = useMeasurePunchouts(['userAccountMenu'], [], {y: -6, height: 6, x: 0, width: 0});
|
||||
const overlayPunchOut = useMeasurePunchouts(['userAccountMenu'], [], {x: -2.5, y: -2.5, width: 5, height: 5});
|
||||
const onDismiss = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
@@ -58,13 +58,12 @@ export const CompleteYourProfileTour = () => {
|
||||
overlayPunchOut={overlayPunchOut}
|
||||
step={steps.STARTED}
|
||||
placement='left-start'
|
||||
pulsatingDotPlacement='left'
|
||||
pulsatingDotPlacement='left-end'
|
||||
pulsatingDotTranslate={translate}
|
||||
handleDismiss={onDismiss}
|
||||
singleTip={true}
|
||||
showOptOut={false}
|
||||
interactivePunchOut={true}
|
||||
zIndex={1058}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ import Phone from 'components/common/svg_images_components/phone_svg';
|
||||
import Security from 'components/common/svg_images_components/security_svg';
|
||||
import Sunglasses from 'components/common/svg_images_components/sunglasses_svg';
|
||||
import LearnMoreTrialModal from 'components/learn_more_trial_modal/learn_more_trial_modal';
|
||||
import {openMenu} from 'components/menu';
|
||||
import {
|
||||
AutoTourStatus,
|
||||
FINISHED,
|
||||
@@ -37,9 +38,9 @@ import {
|
||||
TTNameMapToATStatusKey,
|
||||
TutorialTourName,
|
||||
} from 'components/tours';
|
||||
import {ELEMENT_ID_FOR_USER_ACCOUNT_MENU_BUTTON} from 'components/user_account_menu/user_account_menu';
|
||||
|
||||
import {ModalIdentifiers, TELEMETRY_CATEGORIES} from 'utils/constants';
|
||||
import {clickOnMenuButton, MenuButtonIds} from 'utils/keyboard';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
@@ -239,7 +240,7 @@ export const useHandleOnBoardingTaskTrigger = () => {
|
||||
break;
|
||||
}
|
||||
case OnboardingTasksName.COMPLETE_YOUR_PROFILE: {
|
||||
clickOnMenuButton(MenuButtonIds.userAccountMenu);
|
||||
openMenu(ELEMENT_ID_FOR_USER_ACCOUNT_MENU_BUTTON);
|
||||
dispatch(setShowOnboardingCompleteProfileTour(true));
|
||||
handleSaveData(taskName, TaskNameMapToSteps[taskName].STARTED, true);
|
||||
if (inAdminConsole) {
|
||||
|
||||
@@ -8,10 +8,10 @@ import {useSelector} from 'react-redux';
|
||||
import {makeGetCustomStatus, showPostHeaderUpdateStatusButton, isCustomStatusEnabled} from 'selectors/views/custom_status';
|
||||
|
||||
import CustomStatusEmoji from 'components/custom_status/custom_status_emoji';
|
||||
import {openMenu} from 'components/menu';
|
||||
import {ELEMENT_ID_FOR_USER_ACCOUNT_MENU_BUTTON} from 'components/user_account_menu/user_account_menu';
|
||||
import EmojiIcon from 'components/widgets/icons/emoji_icon';
|
||||
|
||||
import {clickOnMenuButton, MenuButtonIds} from 'utils/keyboard';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
interface ComponentProps {
|
||||
@@ -51,7 +51,7 @@ const PostHeaderCustomStatus = (props: ComponentProps) => {
|
||||
|
||||
const updateStatus = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
clickOnMenuButton(MenuButtonIds.userAccountMenu);
|
||||
openMenu(ELEMENT_ID_FOR_USER_ACCOUNT_MENU_BUTTON);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,7 +18,6 @@ exports[`components/sidebar should match snapshot 1`] = `
|
||||
showMoreChannelsModal={[Function]}
|
||||
showNewChannelModal={[Function]}
|
||||
unreadFilterEnabled={false}
|
||||
userGroupsEnabled={false}
|
||||
/>
|
||||
<div
|
||||
aria-label="channel navigator region"
|
||||
@@ -61,7 +60,6 @@ exports[`components/sidebar should match snapshot when direct channels modal is
|
||||
showMoreChannelsModal={[Function]}
|
||||
showNewChannelModal={[Function]}
|
||||
unreadFilterEnabled={false}
|
||||
userGroupsEnabled={false}
|
||||
/>
|
||||
<div
|
||||
aria-label="channel navigator region"
|
||||
@@ -108,7 +106,6 @@ exports[`components/sidebar should match snapshot when more channels modal is op
|
||||
showMoreChannelsModal={[Function]}
|
||||
showNewChannelModal={[Function]}
|
||||
unreadFilterEnabled={false}
|
||||
userGroupsEnabled={false}
|
||||
/>
|
||||
<div
|
||||
aria-label="channel navigator region"
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
|
||||
import {trackEvent} from 'actions/telemetry_actions';
|
||||
|
||||
import {CreateAndJoinChannelsTour, InvitePeopleTour} from 'components/tours/onboarding_tour';
|
||||
import Menu from 'components/widgets/menu/menu';
|
||||
import MenuWrapper from 'components/widgets/menu/menu_wrapper';
|
||||
import WithTooltip from 'components/with_tooltip';
|
||||
|
||||
type Props = {
|
||||
canCreateChannel: boolean;
|
||||
canJoinPublicChannel: boolean;
|
||||
userGroupsEnabled: boolean;
|
||||
showMoreChannelsModal: () => void;
|
||||
showCreateUserGroupModal: () => void;
|
||||
invitePeopleModal: () => void;
|
||||
showNewChannelModal: () => void;
|
||||
showCreateCategoryModal: () => void;
|
||||
handleOpenDirectMessagesModal: (e: Event) => void;
|
||||
unreadFilterEnabled: boolean;
|
||||
showCreateTutorialTip: boolean;
|
||||
showInviteTutorialTip: boolean;
|
||||
isAddChannelOpen: boolean;
|
||||
openAddChannelOpen: (open: boolean) => void;
|
||||
canCreateCustomGroups: boolean;
|
||||
};
|
||||
|
||||
const AddChannelDropdown = ({
|
||||
canCreateChannel,
|
||||
canJoinPublicChannel,
|
||||
showMoreChannelsModal,
|
||||
showCreateUserGroupModal,
|
||||
invitePeopleModal,
|
||||
showNewChannelModal,
|
||||
showCreateCategoryModal,
|
||||
handleOpenDirectMessagesModal,
|
||||
unreadFilterEnabled,
|
||||
showCreateTutorialTip,
|
||||
showInviteTutorialTip,
|
||||
isAddChannelOpen,
|
||||
openAddChannelOpen,
|
||||
canCreateCustomGroups,
|
||||
}: Props) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const renderDropdownItems = () => {
|
||||
const invitePeople = (
|
||||
<Menu.Group>
|
||||
<Menu.ItemAction
|
||||
id='invitePeople'
|
||||
onClick={invitePeopleModal}
|
||||
icon={<i className='icon-account-plus-outline'/>}
|
||||
text={intl.formatMessage({id: 'sidebar_left.add_channel_dropdown.invitePeople', defaultMessage: 'Invite people'})}
|
||||
extraText={intl.formatMessage({id: 'sidebar_left.add_channel_dropdown.invitePeopleExtraText', defaultMessage: 'Add people to the team'})}
|
||||
/>
|
||||
{showInviteTutorialTip && <InvitePeopleTour/>}
|
||||
</Menu.Group>
|
||||
);
|
||||
|
||||
let joinPublicChannel;
|
||||
if (canJoinPublicChannel) {
|
||||
joinPublicChannel = (
|
||||
<Menu.ItemAction
|
||||
id='showMoreChannels'
|
||||
onClick={showMoreChannelsModal}
|
||||
icon={<i className='icon-globe'/>}
|
||||
text={intl.formatMessage({id: 'sidebar_left.add_channel_dropdown.browseChannels', defaultMessage: 'Browse channels'})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let createChannel;
|
||||
if (canCreateChannel) {
|
||||
createChannel = (
|
||||
<Menu.ItemAction
|
||||
id='showNewChannel'
|
||||
onClick={showNewChannelModal}
|
||||
icon={<i className='icon-plus'/>}
|
||||
text={intl.formatMessage({id: 'sidebar_left.add_channel_dropdown.createNewChannel', defaultMessage: 'Create new channel'})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let createCategory;
|
||||
if (!unreadFilterEnabled) {
|
||||
createCategory = (
|
||||
<Menu.Group>
|
||||
<Menu.ItemAction
|
||||
id='createCategory'
|
||||
onClick={showCreateCategoryModal}
|
||||
icon={<i className='icon-folder-plus-outline'/>}
|
||||
text={intl.formatMessage({id: 'sidebar_left.add_channel_dropdown.createCategory', defaultMessage: 'Create new category'})}
|
||||
/>
|
||||
</Menu.Group>);
|
||||
}
|
||||
|
||||
const createDirectMessage = (
|
||||
<Menu.ItemAction
|
||||
id={'openDirectMessageMenuItem'}
|
||||
onClick={handleOpenDirectMessagesModal}
|
||||
icon={<i className='icon-account-outline'/>}
|
||||
text={intl.formatMessage({id: 'sidebar.openDirectMessage', defaultMessage: 'Open a direct message'})}
|
||||
/>
|
||||
);
|
||||
|
||||
let createUserGroup;
|
||||
if (canCreateCustomGroups) {
|
||||
createUserGroup = (
|
||||
<Menu.ItemAction
|
||||
id={'createUserGroup'}
|
||||
onClick={showCreateUserGroupModal}
|
||||
icon={<i className='icon-account-multiple-plus-outline'/>}
|
||||
text={intl.formatMessage({id: 'sidebar.createUserGroup', defaultMessage: 'Create New User Group'})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Menu.Group>
|
||||
{createChannel}
|
||||
{joinPublicChannel}
|
||||
{createDirectMessage}
|
||||
{showCreateTutorialTip && <CreateAndJoinChannelsTour/>}
|
||||
{createUserGroup}
|
||||
</Menu.Group>
|
||||
{createCategory}
|
||||
{invitePeople}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const trackOpen = (opened: boolean) => {
|
||||
openAddChannelOpen(opened);
|
||||
if (opened) {
|
||||
trackEvent('ui', 'ui_add_channel_dropdown_opened');
|
||||
}
|
||||
};
|
||||
|
||||
if (!(canCreateChannel || canJoinPublicChannel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuWrapper
|
||||
className='AddChannelDropdown'
|
||||
onToggle={trackOpen}
|
||||
open={isAddChannelOpen}
|
||||
>
|
||||
<WithTooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'sidebar_left.add_channel_dropdown.browseOrCreateChannels',
|
||||
defaultMessage: 'Browse or create channels',
|
||||
})}
|
||||
>
|
||||
<button
|
||||
className={'AddChannelDropdown_dropdownButton'}
|
||||
aria-label={intl.formatMessage({id: 'sidebar_left.add_channel_dropdown.dropdownAriaLabel', defaultMessage: 'Add Channel Dropdown'})}
|
||||
>
|
||||
<i className='icon-plus'/>
|
||||
</button>
|
||||
</WithTooltip>
|
||||
<Menu
|
||||
id='AddChannelDropdown'
|
||||
ariaLabel={intl.formatMessage({id: 'sidebar_left.add_channel_dropdown.dropdownAriaLabel', defaultMessage: 'Add Channel Dropdown'})}
|
||||
>
|
||||
{renderDropdownItems()}
|
||||
</Menu>
|
||||
</MenuWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddChannelDropdown;
|
||||
@@ -4,11 +4,11 @@
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
|
||||
import BrowserOrAddChannelMenu from 'components/sidebar/sidebar_header/sidebar_browse_or_add_channel_menu';
|
||||
|
||||
import ChannelNavigator from './channel_navigator';
|
||||
import type {Props} from './channel_navigator';
|
||||
|
||||
import AddChannelDropdown from '../add_channel_dropdown';
|
||||
|
||||
let props: Props;
|
||||
|
||||
describe('Components/ChannelNavigator', () => {
|
||||
@@ -23,8 +23,8 @@ describe('Components/ChannelNavigator', () => {
|
||||
};
|
||||
});
|
||||
|
||||
it('should not show AddChannelDropdown', () => {
|
||||
it('should not show BrowserOrAddChannelMenu', () => {
|
||||
const wrapper = shallow(<ChannelNavigator {...props}/>);
|
||||
expect(wrapper.find(AddChannelDropdown).length).toBe(0);
|
||||
expect(wrapper.find(BrowserOrAddChannelMenu).length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,6 @@ import Sidebar from './sidebar';
|
||||
function mapStateToProps(state: GlobalState) {
|
||||
const currentTeam = getCurrentTeam(state);
|
||||
const unreadFilterEnabled = isUnreadFilterEnabled(state);
|
||||
const userGroupsEnabled = isCustomGroupsEnabled(state);
|
||||
|
||||
let canCreatePublicChannel = false;
|
||||
let canCreatePrivateChannel = false;
|
||||
@@ -41,7 +40,7 @@ function mapStateToProps(state: GlobalState) {
|
||||
canJoinPublicChannel = haveICurrentChannelPermission(state, Permissions.JOIN_PUBLIC_CHANNELS);
|
||||
}
|
||||
|
||||
const canCreateCustomGroups = haveISystemPermission(state, {permission: Permissions.CREATE_CUSTOM_GROUP}) && isCustomGroupsEnabled(state);
|
||||
const canCreateCustomGroups = isCustomGroupsEnabled(state) && haveISystemPermission(state, {permission: Permissions.CREATE_CUSTOM_GROUP});
|
||||
|
||||
return {
|
||||
teamId: currentTeam ? currentTeam.id : '',
|
||||
@@ -52,7 +51,6 @@ function mapStateToProps(state: GlobalState) {
|
||||
unreadFilterEnabled,
|
||||
isMobileView: getIsMobileView(state),
|
||||
isKeyBoardShortcutModalOpen: isModalOpen(state, ModalIdentifiers.KEYBOARD_SHORTCUTS_MODAL),
|
||||
userGroupsEnabled,
|
||||
canCreateCustomGroups,
|
||||
rhsState: getRhsState(state),
|
||||
rhsOpen: getIsRhsOpen(state),
|
||||
|
||||
@@ -48,7 +48,6 @@ type Props = {
|
||||
unreadFilterEnabled: boolean;
|
||||
isMobileView: boolean;
|
||||
isKeyBoardShortcutModalOpen: boolean;
|
||||
userGroupsEnabled: boolean;
|
||||
canCreateCustomGroups: boolean;
|
||||
rhsState?: RhsState;
|
||||
rhsOpen?: boolean;
|
||||
@@ -180,8 +179,8 @@ export default class Sidebar extends React.PureComponent<Props, State> {
|
||||
trackEvent('ui', 'ui_channels_create_user_group');
|
||||
};
|
||||
|
||||
handleOpenMoreDirectChannelsModal = (e: Event) => {
|
||||
e.preventDefault();
|
||||
handleOpenMoreDirectChannelsModal = (e?: Event) => {
|
||||
e?.preventDefault();
|
||||
if (this.state.showDirectChannelsModal) {
|
||||
this.hideMoreDirectChannelsModal();
|
||||
} else {
|
||||
@@ -248,7 +247,6 @@ export default class Sidebar extends React.PureComponent<Props, State> {
|
||||
canJoinPublicChannel={this.props.canJoinPublicChannel}
|
||||
handleOpenDirectMessagesModal={this.handleOpenMoreDirectChannelsModal}
|
||||
unreadFilterEnabled={this.props.unreadFilterEnabled}
|
||||
userGroupsEnabled={this.props.userGroupsEnabled}
|
||||
canCreateCustomGroups={this.props.canCreateCustomGroups}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import SidebarHeader from './sidebar_header';
|
||||
|
||||
export default SidebarHeader;
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {FormattedMessage, useIntl} from 'react-intl';
|
||||
|
||||
import {
|
||||
PlusIcon,
|
||||
AccountPlusOutlineIcon,
|
||||
FolderPlusOutlineIcon,
|
||||
AccountMultiplePlusOutlineIcon,
|
||||
GlobeIcon,
|
||||
AccountOutlineIcon,
|
||||
} from '@mattermost/compass-icons/components';
|
||||
|
||||
import * as Menu from 'components/menu';
|
||||
import {OnboardingTourSteps} from 'components/tours';
|
||||
import {useShowOnboardingTutorialStep, CreateAndJoinChannelsTour, InvitePeopleTour} from 'components/tours/onboarding_tour';
|
||||
|
||||
export const ELEMENT_ID_FOR_BROWSE_OR_ADD_CHANNEL_MENU = 'browseOrAddChannelMenuButton';
|
||||
|
||||
type Props = {
|
||||
canCreateChannel: boolean;
|
||||
onCreateNewChannelClick: () => void;
|
||||
canJoinPublicChannel: boolean;
|
||||
onBrowseChannelClick: () => void;
|
||||
onOpenDirectMessageClick: () => void;
|
||||
canCreateCustomGroups: boolean;
|
||||
onCreateNewUserGroupClick: () => void;
|
||||
unreadFilterEnabled: boolean;
|
||||
onCreateNewCategoryClick: () => void;
|
||||
onInvitePeopleClick: () => void;
|
||||
};
|
||||
|
||||
export default function SidebarBrowserOrAddChannelMenu(props: Props) {
|
||||
const {formatMessage} = useIntl();
|
||||
|
||||
const showCreateAndJoinChannelsTutorialTip = useShowOnboardingTutorialStep(OnboardingTourSteps.CREATE_AND_JOIN_CHANNELS);
|
||||
const showInvitePeopleTutorialTip = useShowOnboardingTutorialStep(OnboardingTourSteps.INVITE_PEOPLE);
|
||||
|
||||
let createNewChannelMenuItem: JSX.Element | null = null;
|
||||
if (props.canCreateChannel) {
|
||||
createNewChannelMenuItem = (
|
||||
<Menu.Item
|
||||
id='createNewChannelMenuItem'
|
||||
onClick={props.onCreateNewChannelClick}
|
||||
leadingElement={<PlusIcon size={18}/>}
|
||||
labels={(
|
||||
<FormattedMessage
|
||||
id='sidebarLeft.browserOrCreateChannelMenu.createNewChannelMenuItem.primaryLabel'
|
||||
defaultMessage='Create new channel'
|
||||
/>
|
||||
)}
|
||||
trailingElements={showCreateAndJoinChannelsTutorialTip && <CreateAndJoinChannelsTour/>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let browseChannelsMenuItem: JSX.Element | null = null;
|
||||
if (props.canJoinPublicChannel) {
|
||||
browseChannelsMenuItem = (
|
||||
<Menu.Item
|
||||
id='browseChannelsMenuItem'
|
||||
onClick={props.onBrowseChannelClick}
|
||||
leadingElement={<GlobeIcon size={18}/>}
|
||||
labels={(
|
||||
<FormattedMessage
|
||||
id='sidebarLeft.browserOrCreateChannelMenu.browseChannelsMenuItem.primaryLabel'
|
||||
defaultMessage='Browse channels'
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const createDirectMessageMenuItem = (
|
||||
<Menu.Item
|
||||
id='openDirectMessageMenuItem'
|
||||
onClick={props.onOpenDirectMessageClick}
|
||||
leadingElement={<AccountOutlineIcon size={18}/>}
|
||||
labels={(
|
||||
<FormattedMessage
|
||||
id='sidebarLeft.browserOrCreateChannelMenu.openDirectMessageMenuItem.primaryLabel'
|
||||
defaultMessage='Open a direct message'
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
let createUserGroupMenuItem: JSX.Element | null = null;
|
||||
if (props.canCreateCustomGroups) {
|
||||
createUserGroupMenuItem = (
|
||||
<Menu.Item
|
||||
id='createUserGroupMenuItem'
|
||||
onClick={props.onCreateNewUserGroupClick}
|
||||
leadingElement={<AccountMultiplePlusOutlineIcon size={18}/>}
|
||||
labels={(
|
||||
<FormattedMessage
|
||||
id='sidebarLeft.browserOrCreateChannelMenu.createUserGroupMenuItem.primaryLabel'
|
||||
defaultMessage='Create new user group'
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let createNewCategoryMenuItem: JSX.Element | null = null;
|
||||
if (!props.unreadFilterEnabled) {
|
||||
createNewCategoryMenuItem = (
|
||||
<Menu.Item
|
||||
id='createCategoryMenuItem'
|
||||
onClick={props.onCreateNewCategoryClick}
|
||||
leadingElement={<FolderPlusOutlineIcon size={18}/>}
|
||||
labels={(
|
||||
<FormattedMessage
|
||||
id='sidebarLeft.browserOrCreateChannelMenu.createCategoryMenuItem.primaryLabel'
|
||||
defaultMessage='Create new category'
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const invitePeopleMenuItem = (
|
||||
<Menu.Item
|
||||
id='invitePeopleMenuItem'
|
||||
onClick={props.onInvitePeopleClick}
|
||||
leadingElement={<AccountPlusOutlineIcon size={18}/>}
|
||||
labels={(
|
||||
<>
|
||||
<FormattedMessage
|
||||
id='sidebarLeft.browserOrCreateChannelMenu.invitePeopleMenuItem.primaryLabel'
|
||||
defaultMessage='Invite people'
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='sidebarLeft.browserOrCreateChannelMenu.invitePeopleMenuItem.secondaryLabel'
|
||||
defaultMessage='Add people to the team'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
trailingElements={showInvitePeopleTutorialTip && <InvitePeopleTour/>}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Menu.Container
|
||||
menuButton={{
|
||||
id: ELEMENT_ID_FOR_BROWSE_OR_ADD_CHANNEL_MENU,
|
||||
'aria-label': formatMessage({
|
||||
id: 'sidebarLeft.browserOrCreateChannelMenuButton.label',
|
||||
defaultMessage: 'Browse or create channels',
|
||||
}),
|
||||
class: 'btn btn-icon btn-sm btn-tertiary btn-inverted btn-round',
|
||||
children: <PlusIcon size={18}/>,
|
||||
}}
|
||||
menuButtonTooltip={{
|
||||
text: formatMessage({id: 'sidebarLeft.browserOrCreateChannelMenuButton.label', defaultMessage: 'Browse or create channels'}),
|
||||
}}
|
||||
menu={{
|
||||
id: 'browserOrAddChannelMenu',
|
||||
'aria-labelledby': ELEMENT_ID_FOR_BROWSE_OR_ADD_CHANNEL_MENU,
|
||||
}}
|
||||
>
|
||||
{createNewChannelMenuItem}
|
||||
{browseChannelsMenuItem}
|
||||
{createDirectMessageMenuItem}
|
||||
{createUserGroupMenuItem}
|
||||
{Boolean(createNewCategoryMenuItem) &&
|
||||
<Menu.Separator/>
|
||||
}
|
||||
{createNewCategoryMenuItem}
|
||||
<Menu.Separator/>
|
||||
{invitePeopleMenuItem}
|
||||
</Menu.Container>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
.sidebarHeaderContainer {
|
||||
display: flex;
|
||||
height: 55px;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.sidebarHeader {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
|
||||
@@ -9,11 +9,10 @@ import IconButton from '@mattermost/compass-components/components/icon-button';
|
||||
import {CloudProducts} from 'utils/constants';
|
||||
import {FileSizes} from 'utils/file_utils';
|
||||
|
||||
import BrowserOrAddChannelMenu from './sidebar_browse_or_add_channel_menu';
|
||||
import SidebarHeader from './sidebar_header';
|
||||
import type {Props} from './sidebar_header';
|
||||
|
||||
import AddChannelDropdown from '../add_channel_dropdown';
|
||||
|
||||
let props: Props;
|
||||
|
||||
const mockDispatch = jest.fn();
|
||||
@@ -37,7 +36,6 @@ describe('Components/SidebarHeader', () => {
|
||||
handleOpenDirectMessagesModal: jest.fn(),
|
||||
unreadFilterEnabled: true,
|
||||
showCreateUserGroupModal: jest.fn(),
|
||||
userGroupsEnabled: false,
|
||||
canCreateCustomGroups: true,
|
||||
};
|
||||
|
||||
@@ -130,9 +128,9 @@ describe('Components/SidebarHeader', () => {
|
||||
};
|
||||
});
|
||||
|
||||
it('should show AddChannelDropdown', () => {
|
||||
it('should show BrowserOrAddChannelMenu', () => {
|
||||
const wrapper = shallow(<SidebarHeader {...props}/>);
|
||||
expect(wrapper.find(AddChannelDropdown).length).toBe(1);
|
||||
expect(wrapper.find(BrowserOrAddChannelMenu).length).toBe(1);
|
||||
});
|
||||
|
||||
it('should embed teams menu dropdown into heading', () => {
|
||||
|
||||
@@ -1,58 +1,20 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback, useState} from 'react';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
import React, {useState} from 'react';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
import Flex from '@mattermost/compass-components/utilities/layout/Flex'; // eslint-disable-line no-restricted-imports
|
||||
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {setAddChannelDropdown} from 'actions/views/add_channel_dropdown';
|
||||
import {isAddChannelDropdownOpen} from 'selectors/views/add_channel_dropdown';
|
||||
|
||||
import useGetUsageDeltas from 'components/common/hooks/useGetUsageDeltas';
|
||||
import CompassThemeProvider from 'components/compass_theme_provider/compass_theme_provider';
|
||||
import MainMenu from 'components/main_menu';
|
||||
import AddChannelDropdown from 'components/sidebar/add_channel_dropdown';
|
||||
import {OnboardingTourSteps} from 'components/tours';
|
||||
import {useShowOnboardingTutorialStep} from 'components/tours/onboarding_tour';
|
||||
import MenuWrapper from 'components/widgets/menu/menu_wrapper';
|
||||
import WithTooltip from 'components/with_tooltip';
|
||||
|
||||
import SidebarBrowseOrAddChannelMenu from './sidebar_browse_or_add_channel_menu';
|
||||
|
||||
import './sidebar_header.scss';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
type SidebarHeaderContainerProps = {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
const SidebarHeaderContainer = styled(Flex).attrs(() => ({
|
||||
element: 'header',
|
||||
row: true,
|
||||
justify: 'space-between',
|
||||
alignment: 'center',
|
||||
}))<SidebarHeaderContainerProps>`
|
||||
height: 55px;
|
||||
padding: 0 16px;
|
||||
gap: 8px;
|
||||
|
||||
.dropdown-menu {
|
||||
position: absolute;
|
||||
transform: translate(0, 0);
|
||||
margin-left: 0;
|
||||
min-width: 210px;
|
||||
}
|
||||
|
||||
#SidebarContainer & .AddChannelDropdown_dropdownButton {
|
||||
border-radius: 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
`;
|
||||
|
||||
export type Props = {
|
||||
showNewChannelModal: () => void;
|
||||
showMoreChannelsModal: () => void;
|
||||
@@ -61,23 +23,14 @@ export type Props = {
|
||||
showCreateCategoryModal: () => void;
|
||||
canCreateChannel: boolean;
|
||||
canJoinPublicChannel: boolean;
|
||||
handleOpenDirectMessagesModal: (e: Event) => void;
|
||||
handleOpenDirectMessagesModal: () => void;
|
||||
unreadFilterEnabled: boolean;
|
||||
userGroupsEnabled: boolean;
|
||||
canCreateCustomGroups: boolean;
|
||||
}
|
||||
|
||||
const SidebarHeader = (props: Props) => {
|
||||
const dispatch = useDispatch();
|
||||
const currentTeam = useSelector((state: GlobalState) => getCurrentTeam(state));
|
||||
const showCreateTutorialTip = useShowOnboardingTutorialStep(OnboardingTourSteps.CREATE_AND_JOIN_CHANNELS);
|
||||
const showInviteTutorialTip = useShowOnboardingTutorialStep(OnboardingTourSteps.INVITE_PEOPLE);
|
||||
const currentTeam = useSelector(getCurrentTeam);
|
||||
const usageDeltas = useGetUsageDeltas();
|
||||
const isAddChannelOpen = useSelector(isAddChannelDropdownOpen);
|
||||
const theme = useSelector(getTheme);
|
||||
const openAddChannelOpen = useCallback((open: boolean) => {
|
||||
dispatch(setAddChannelDropdown(open));
|
||||
}, []);
|
||||
|
||||
const [menuToggled, setMenuToggled] = useState(false);
|
||||
|
||||
@@ -90,48 +43,44 @@ const SidebarHeader = (props: Props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<CompassThemeProvider theme={theme}>
|
||||
<SidebarHeaderContainer
|
||||
id={'sidebar-header-container'}
|
||||
<header
|
||||
id='sidebar-header-container'
|
||||
className='sidebarHeaderContainer'
|
||||
>
|
||||
<MenuWrapper
|
||||
onToggle={handleMenuToggle}
|
||||
className='SidebarHeaderMenuWrapper test-team-header'
|
||||
>
|
||||
<MenuWrapper
|
||||
onToggle={handleMenuToggle}
|
||||
className='SidebarHeaderMenuWrapper test-team-header'
|
||||
<WithTooltip
|
||||
title={currentTeam.description ? currentTeam.description : currentTeam.display_name}
|
||||
>
|
||||
<WithTooltip
|
||||
title={currentTeam.description ? currentTeam.description : currentTeam.display_name}
|
||||
>
|
||||
<h1 className='sidebarHeader'>
|
||||
<button className='style--none sidebar-header'>
|
||||
<span className='title'>{currentTeam.display_name}</span>
|
||||
<i className='icon icon-chevron-down'/>
|
||||
</button>
|
||||
</h1>
|
||||
</WithTooltip>
|
||||
<MainMenu
|
||||
id='sidebarDropdownMenu'
|
||||
usageDeltaTeams={usageDeltas.teams.active}
|
||||
/>
|
||||
</MenuWrapper>
|
||||
<AddChannelDropdown
|
||||
showNewChannelModal={props.showNewChannelModal}
|
||||
showMoreChannelsModal={props.showMoreChannelsModal}
|
||||
invitePeopleModal={props.invitePeopleModal}
|
||||
showCreateCategoryModal={props.showCreateCategoryModal}
|
||||
canCreateChannel={props.canCreateChannel}
|
||||
canJoinPublicChannel={props.canJoinPublicChannel}
|
||||
handleOpenDirectMessagesModal={props.handleOpenDirectMessagesModal}
|
||||
unreadFilterEnabled={props.unreadFilterEnabled}
|
||||
showCreateTutorialTip={showCreateTutorialTip}
|
||||
showInviteTutorialTip={showInviteTutorialTip}
|
||||
isAddChannelOpen={isAddChannelOpen}
|
||||
openAddChannelOpen={openAddChannelOpen}
|
||||
canCreateCustomGroups={props.canCreateCustomGroups}
|
||||
showCreateUserGroupModal={props.showCreateUserGroupModal}
|
||||
userGroupsEnabled={props.userGroupsEnabled}
|
||||
<h1 className='sidebarHeader'>
|
||||
<button className='style--none sidebar-header'>
|
||||
<span className='title'>{currentTeam.display_name}</span>
|
||||
<i className='icon icon-chevron-down'/>
|
||||
</button>
|
||||
</h1>
|
||||
</WithTooltip>
|
||||
<MainMenu
|
||||
id='sidebarDropdownMenu'
|
||||
usageDeltaTeams={usageDeltas.teams.active}
|
||||
/>
|
||||
</SidebarHeaderContainer>
|
||||
</CompassThemeProvider>
|
||||
</MenuWrapper>
|
||||
{(props.canCreateChannel || props.canJoinPublicChannel) && (
|
||||
<SidebarBrowseOrAddChannelMenu
|
||||
canCreateChannel={props.canCreateChannel}
|
||||
onCreateNewChannelClick={props.showNewChannelModal}
|
||||
canJoinPublicChannel={props.canJoinPublicChannel}
|
||||
onBrowseChannelClick={props.showMoreChannelsModal}
|
||||
onOpenDirectMessageClick={props.handleOpenDirectMessagesModal}
|
||||
canCreateCustomGroups={props.canCreateCustomGroups}
|
||||
onCreateNewUserGroupClick={props.showCreateUserGroupModal}
|
||||
unreadFilterEnabled={props.unreadFilterEnabled}
|
||||
onCreateNewCategoryClick={props.showCreateCategoryModal}
|
||||
onInvitePeopleClick={props.invitePeopleModal}
|
||||
/>
|
||||
)}
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -76,13 +76,13 @@ exports[`components/threading/channel_threads/thread_footer should report total
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/5/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="5"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -147,13 +147,13 @@ exports[`components/threading/channel_threads/thread_footer should report total
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/4/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="4"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -218,13 +218,13 @@ exports[`components/threading/channel_threads/thread_footer should report total
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/3/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="3"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -587,13 +587,13 @@ exports[`components/threading/channel_threads/thread_footer should show unread i
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/5/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="5"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -658,13 +658,13 @@ exports[`components/threading/channel_threads/thread_footer should show unread i
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/4/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="4"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -729,13 +729,13 @@ exports[`components/threading/channel_threads/thread_footer should show unread i
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/3/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="3"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
|
||||
@@ -8,11 +8,12 @@ import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
import {getCurrentRelativeTeamUrl} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getCurrentUserId, isCurrentUserGuestUser} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {setAddChannelDropdown} from 'actions/views/add_channel_dropdown';
|
||||
import {close as closeLhs, open as openLhs} from 'actions/views/lhs';
|
||||
import {switchToChannels} from 'actions/views/onboarding_tasks';
|
||||
|
||||
import {openMenu, dismissMenu} from 'components/menu';
|
||||
import {OnboardingTaskCategory, OnboardingTaskList, OnboardingTasksName} from 'components/onboarding_tasks';
|
||||
import {ELEMENT_ID_FOR_BROWSE_OR_ADD_CHANNEL_MENU} from 'components/sidebar/sidebar_header/sidebar_browse_or_add_channel_menu';
|
||||
|
||||
import {getHistory} from 'utils/browser_history';
|
||||
|
||||
@@ -51,11 +52,11 @@ export const useHandleNavigationAndExtraActions = (tourCategory: string) => {
|
||||
break;
|
||||
}
|
||||
case OnboardingTourSteps.CREATE_AND_JOIN_CHANNELS : {
|
||||
dispatch(setAddChannelDropdown(true));
|
||||
openMenu(ELEMENT_ID_FOR_BROWSE_OR_ADD_CHANNEL_MENU);
|
||||
break;
|
||||
}
|
||||
case OnboardingTourSteps.INVITE_PEOPLE : {
|
||||
dispatch(setAddChannelDropdown(true));
|
||||
openMenu(ELEMENT_ID_FOR_BROWSE_OR_ADD_CHANNEL_MENU);
|
||||
break;
|
||||
}
|
||||
case OnboardingTourSteps.SEND_MESSAGE : {
|
||||
@@ -107,11 +108,11 @@ export const useHandleNavigationAndExtraActions = (tourCategory: string) => {
|
||||
if (tourCategory === TutorialTourName.ONBOARDING_TUTORIAL_STEP) {
|
||||
switch (lastStep) {
|
||||
case OnboardingTourSteps.CREATE_AND_JOIN_CHANNELS : {
|
||||
dispatch(setAddChannelDropdown(false));
|
||||
dismissMenu();
|
||||
break;
|
||||
}
|
||||
case OnboardingTourSteps.INVITE_PEOPLE : {
|
||||
dispatch(setAddChannelDropdown(false));
|
||||
dismissMenu();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -8,7 +8,7 @@ import {useMeasurePunchouts} from '@mattermost/components';
|
||||
|
||||
import OnboardingTourTip from './onboarding_tour_tip';
|
||||
|
||||
const translate = {x: 0, y: 70};
|
||||
const translate = {x: -3, y: 13};
|
||||
|
||||
export const CreateAndJoinChannelsTour = () => {
|
||||
const title = (
|
||||
@@ -26,7 +26,7 @@ export const CreateAndJoinChannelsTour = () => {
|
||||
</p>
|
||||
);
|
||||
|
||||
const overlayPunchOut = useMeasurePunchouts(['showMoreChannels', 'showNewChannel'], [], {y: -8, height: 16, x: 0, width: 0});
|
||||
const overlayPunchOut = useMeasurePunchouts(['browserOrAddChannelMenu'], [], {x: -2.5, y: -2.5, width: 5, height: 5});
|
||||
|
||||
return (
|
||||
<OnboardingTourTip
|
||||
|
||||
@@ -8,7 +8,7 @@ import {useMeasurePunchouts} from '@mattermost/components';
|
||||
|
||||
import OnboardingTourTip from './onboarding_tour_tip';
|
||||
|
||||
const translate = {x: 0, y: -18};
|
||||
const translate = {x: -3, y: -25};
|
||||
|
||||
export const InvitePeopleTour = () => {
|
||||
const title = (
|
||||
@@ -26,7 +26,7 @@ export const InvitePeopleTour = () => {
|
||||
</p>
|
||||
);
|
||||
|
||||
const overlayPunchOut = useMeasurePunchouts(['invitePeople'], [], {y: -8, height: 16, x: 0, width: 0});
|
||||
const overlayPunchOut = useMeasurePunchouts(['browserOrAddChannelMenu'], [], {x: -2.5, y: -2.5, width: 5, height: 5});
|
||||
|
||||
return (
|
||||
<OnboardingTourTip
|
||||
|
||||
@@ -29,6 +29,8 @@ import './user_account_menu.scss';
|
||||
|
||||
type Props = PropsFromRedux;
|
||||
|
||||
export const ELEMENT_ID_FOR_USER_ACCOUNT_MENU_BUTTON = 'userAccountMenuButton';
|
||||
|
||||
export default function UserAccountMenu(props: Props) {
|
||||
const {formatMessage} = useIntl();
|
||||
|
||||
@@ -46,7 +48,7 @@ export default function UserAccountMenu(props: Props) {
|
||||
return (
|
||||
<Menu.Container
|
||||
menuButton={{
|
||||
id: 'userAccountMenuButton',
|
||||
id: ELEMENT_ID_FOR_USER_ACCOUNT_MENU_BUTTON,
|
||||
class: classNames('userAccountMenu_menuButton', {
|
||||
withCustomStatus: isCustomStatusSet,
|
||||
}),
|
||||
|
||||
@@ -30,13 +30,13 @@ exports[`components/widgets/users/Avatars should fetch missing users 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/1/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="1"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -101,13 +101,13 @@ exports[`components/widgets/users/Avatars should fetch missing users 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/6/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="6"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -172,13 +172,13 @@ exports[`components/widgets/users/Avatars should fetch missing users 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/7/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="7"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -302,13 +302,13 @@ exports[`components/widgets/users/Avatars should properly count overflow 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/1/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="1"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -373,13 +373,13 @@ exports[`components/widgets/users/Avatars should properly count overflow 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/2/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="2"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -444,13 +444,13 @@ exports[`components/widgets/users/Avatars should properly count overflow 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/3/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="3"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -572,13 +572,13 @@ exports[`components/widgets/users/Avatars should support userIds 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/1/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="1"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -643,13 +643,13 @@ exports[`components/widgets/users/Avatars should support userIds 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/2/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="2"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@@ -714,13 +714,13 @@ exports[`components/widgets/users/Avatars should support userIds 1`] = `
|
||||
<ProfilePopoverController
|
||||
src="/api/v4/users/3/image?_=0"
|
||||
triggerComponentAs="button"
|
||||
triggerComponentClass="style--none rounded-button"
|
||||
triggerComponentClass="style--none btn-round"
|
||||
userId="3"
|
||||
>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
className="style--none rounded-button"
|
||||
className="style--none btn-round"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
|
||||
@@ -63,7 +63,7 @@ function UserAvatar({
|
||||
return (
|
||||
<ProfilePopover<HTMLButtonElement>
|
||||
triggerComponentAs='button'
|
||||
triggerComponentClass='style--none rounded-button'
|
||||
triggerComponentClass='style--none btn-round'
|
||||
userId={userId}
|
||||
src={profilePictureURL}
|
||||
>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@use 'utils/variables';
|
||||
|
||||
.tooltipContainer {
|
||||
z-index: variables.$z-index-popover;
|
||||
z-index: variables.$z-index-tooltip;
|
||||
max-width: 220px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
|
||||
@@ -5128,12 +5128,8 @@
|
||||
"shortcuts.team_nav.switcher.mac": "Navigate to a specific team:\t⌘|⌥|[1-9]",
|
||||
"sidebar_left.add_channel_cta_dropdown.dropdownAriaLabel": "Add Channel Dropdown",
|
||||
"sidebar_left.add_channel_dropdown.browseChannels": "Browse channels",
|
||||
"sidebar_left.add_channel_dropdown.browseOrCreateChannels": "Browse or create channels",
|
||||
"sidebar_left.add_channel_dropdown.createCategory": "Create new category",
|
||||
"sidebar_left.add_channel_dropdown.createNewChannel": "Create new channel",
|
||||
"sidebar_left.add_channel_dropdown.dropdownAriaLabel": "Add Channel Dropdown",
|
||||
"sidebar_left.add_channel_dropdown.invitePeople": "Invite people",
|
||||
"sidebar_left.add_channel_dropdown.invitePeopleExtraText": "Add people to the team",
|
||||
"sidebar_left.addChannelsCta": "Add channels",
|
||||
"sidebar_left.channel_filter.filterByUnread": "Filter by unread",
|
||||
"sidebar_left.channel_filter.filterUnreadAria": "unreads filter",
|
||||
@@ -5192,7 +5188,6 @@
|
||||
"sidebar_right_menu.flagged": "Saved messages",
|
||||
"sidebar_right_menu.recentMentions": "Recent Mentions",
|
||||
"sidebar.createDirectMessage": "Write a direct message",
|
||||
"sidebar.createUserGroup": "Create New User Group",
|
||||
"sidebar.directchannel.you": "{displayname} (you)",
|
||||
"sidebar.menu.item.notSelected": "not selected",
|
||||
"sidebar.menu.item.selected": "selected",
|
||||
@@ -5211,6 +5206,14 @@
|
||||
"sidebar.types.favorites": "FAVORITES",
|
||||
"sidebar.types.unreads": "UNREADS",
|
||||
"sidebar.unreads": "More unreads",
|
||||
"sidebarLeft.browserOrCreateChannelMenu.browseChannelsMenuItem.primaryLabel": "Browse channels",
|
||||
"sidebarLeft.browserOrCreateChannelMenu.createCategoryMenuItem.primaryLabel": "Create new category",
|
||||
"sidebarLeft.browserOrCreateChannelMenu.createNewChannelMenuItem.primaryLabel": "Create new channel",
|
||||
"sidebarLeft.browserOrCreateChannelMenu.createUserGroupMenuItem.primaryLabel": "Create new user group",
|
||||
"sidebarLeft.browserOrCreateChannelMenu.invitePeopleMenuItem.primaryLabel": "Invite people",
|
||||
"sidebarLeft.browserOrCreateChannelMenu.invitePeopleMenuItem.secondaryLabel": "Add people to the team",
|
||||
"sidebarLeft.browserOrCreateChannelMenu.openDirectMessageMenuItem.primaryLabel": "Open a direct message",
|
||||
"sidebarLeft.browserOrCreateChannelMenuButton.label": "Browse or create channels",
|
||||
"signup_team_system_console": "Go to System Console",
|
||||
"signup_team.guest_without_channels": "Your guest account has no channels assigned. Please contact an administrator.",
|
||||
"signup_team.join_open": "Teams you can join: ",
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import {ActionTypes} from 'utils/constants';
|
||||
|
||||
import type {MMAction} from 'types/store';
|
||||
|
||||
export function isOpen(state = false, action: MMAction) {
|
||||
switch (action.type) {
|
||||
case ActionTypes.ADD_CHANNEL_DROPDOWN_TOGGLE:
|
||||
return action.open;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
isOpen,
|
||||
});
|
||||
@@ -4,7 +4,6 @@
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import addChannelCtaDropdown from './add_channel_cta_dropdown';
|
||||
import addChannelDropdown from './add_channel_dropdown';
|
||||
import admin from './admin';
|
||||
import announcementBar from './announcement_bar';
|
||||
import browser from './browser';
|
||||
@@ -49,7 +48,6 @@ export default combineReducers({
|
||||
marketplace,
|
||||
textbox,
|
||||
channelSidebar,
|
||||
addChannelDropdown,
|
||||
addChannelCtaDropdown,
|
||||
onboardingTasks,
|
||||
threads,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.rounded-button {
|
||||
.btn-round {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,10 @@ button {
|
||||
outline: none !important;
|
||||
transition: all 0.15s ease;
|
||||
|
||||
&.btn-round {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&.btn-icon {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
@@ -298,6 +302,20 @@ button {
|
||||
}
|
||||
}
|
||||
}
|
||||
&.btn-tertiary.btn-inverted {
|
||||
background-color: rgba(var(--sidebar-text-rgb), 0.12);
|
||||
color: rgba(var(--sidebar-text-rgb), 1);
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(var(--sidebar-text-rgb), 0.16);
|
||||
}
|
||||
|
||||
&:active,
|
||||
&[aria-expanded="true"][aria-haspopup="true"] {
|
||||
background-color: rgb(var(--sidebar-text-rgb), 0.24);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-quaternary {
|
||||
background: transparent;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
.app__body {
|
||||
.modal {
|
||||
z-index: variables.$z-index-modal;
|
||||
color: rgb(var(--center-channel-color-rgb));
|
||||
|
||||
.modal-content {
|
||||
|
||||
@@ -161,7 +161,6 @@ $sidebarOpacityAnimationDuration: 0.15s;
|
||||
&.desktop {
|
||||
display: block;
|
||||
|
||||
.AddChannelDropdown_dropdownButton,
|
||||
.SidebarFilters_filterButton,
|
||||
.SidebarChannelNavigator_backButton,
|
||||
.SidebarChannelNavigator_inviteUsers,
|
||||
@@ -178,7 +177,6 @@ $sidebarOpacityAnimationDuration: 0.15s;
|
||||
&.webapp {
|
||||
display: flex;
|
||||
|
||||
.AddChannelDropdown_dropdownButton,
|
||||
.SidebarChannelNavigator_inviteUsers,
|
||||
.SidebarChannelNavigator_jumpToButton,
|
||||
.SidebarFilters_filterButton {
|
||||
@@ -228,7 +226,6 @@ $sidebarOpacityAnimationDuration: 0.15s;
|
||||
}
|
||||
}
|
||||
|
||||
.AddChannelDropdown_dropdownButton,
|
||||
.SidebarChannelNavigator_inviteUsers,
|
||||
.SidebarChannelNavigator_jumpToButton,
|
||||
.SidebarFilters_filterButtontton,
|
||||
@@ -331,35 +328,6 @@ $sidebarOpacityAnimationDuration: 0.15s;
|
||||
color: var(--sidebar-bg);
|
||||
}
|
||||
|
||||
.AddChannelDropdown {
|
||||
height: 30px;
|
||||
|
||||
.dropdown-menu {
|
||||
min-width: 250px;
|
||||
margin-top: 0;
|
||||
line-height: 19px;
|
||||
|
||||
span {
|
||||
color: rgba(var(--center-channel-color-rgb), 0.9);
|
||||
|
||||
&:not(.MenuItem__help-text) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 1px 16px;
|
||||
}
|
||||
|
||||
i {
|
||||
color: rgba(var(--center-channel-color-rgb), 0.64);
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.AddChannelDropdown_dropdownButton,
|
||||
.SidebarChannelNavigator_inviteUsers {
|
||||
z-index: 1;
|
||||
width: 28px;
|
||||
@@ -372,18 +340,6 @@ $sidebarOpacityAnimationDuration: 0.15s;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.AddChannelDropdown_dropdownButton:hover,
|
||||
.AddChannelDropdown_dropdownButton:active,
|
||||
.AddChannelDropdown_dropdownButton:focus {
|
||||
background-color: rgba(var(--sidebar-text-rgb), 0.16);
|
||||
color: var(--sidebar-text);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.AddChannelDropdown_dropdownButton:focus {
|
||||
outline-style: none;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
@@ -408,11 +364,6 @@ $sidebarOpacityAnimationDuration: 0.15s;
|
||||
}
|
||||
}
|
||||
|
||||
.AddChannelDropdown_dropdownButton {
|
||||
background-color: rgba(var(--sidebar-text-rgb), 0.08);
|
||||
color: rgba(var(--sidebar-text-rgb), 0.64);
|
||||
}
|
||||
|
||||
.SidebarMenu {
|
||||
opacity: 1;
|
||||
|
||||
|
||||
@@ -368,7 +368,6 @@
|
||||
|
||||
.post,
|
||||
.SidebarMenu,
|
||||
.AddChannelDropdown,
|
||||
.GlobalThreads {
|
||||
.Menu {
|
||||
position: fixed;
|
||||
@@ -1555,8 +1554,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.SidebarMenu,
|
||||
.AddChannelDropdown {
|
||||
.SidebarMenu {
|
||||
display: block !important;
|
||||
|
||||
.Menu {
|
||||
|
||||
@@ -37,12 +37,33 @@ $elevation-4: var(--elevation-4);
|
||||
$elevation-5: var(--elevation-5);
|
||||
$elevation-6: var(--elevation-6);
|
||||
|
||||
// Z-Index
|
||||
// Central place to manage z-index values for the app, providing a consistent way to manage stacking order.
|
||||
$z-index-popover: 1070;
|
||||
$z-index-user-group-popover: 1060;
|
||||
$z-index-tour-tips: 1058;
|
||||
$z-index-menu: 1054;
|
||||
// ********************
|
||||
// Z-Index Management
|
||||
// Central place to manage z-index values for the app, providing a consistent way to manage the stacking order.
|
||||
// Great care should be taken before making changes, followed by extensive UI testing.
|
||||
// Note : not all defined here are being imported, check usages
|
||||
// ********************
|
||||
|
||||
// Since they can be used on any modal, menu or popover for now they are highest
|
||||
$z-index-tooltip: 1350;
|
||||
|
||||
// Tour tips also open on menus, so they should be higher than menus
|
||||
// Since tippy requires passing zIndex as prop, we have it as constant DEFAULT_Z_INDEX_TOUR_TIPS_POPOVER
|
||||
$z-index-tour-tips-popover: 1300;
|
||||
// Since tour tips are in package/components, we have also defined this in its own scss file
|
||||
// backdrop are dark screen behind the tour tips with a cutout for the highlighted element
|
||||
$z-index-tour-tips-backdrop: 1250;
|
||||
|
||||
// Since menus can appear on either popovers or modal, make it higher than them
|
||||
$z-index-menu: 1100;
|
||||
|
||||
// Modals require attention and should be layered above other popovers
|
||||
$z-index-modal: 1050;
|
||||
|
||||
$z-index-popover: 1200;
|
||||
// Lower than popover because user group popover can open user's popover over it
|
||||
$z-index-user-group-popover: 1150;
|
||||
|
||||
$z-index-global-header: 99;
|
||||
|
||||
$z-index-channel-header: 15;
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
export function isAddChannelDropdownOpen(state: GlobalState) {
|
||||
return state.views.addChannelDropdown.isOpen;
|
||||
}
|
||||
|
||||
export function isAddChannelCtaDropdownOpen(state: GlobalState) {
|
||||
return state.views.addChannelCtaDropdown.isOpen;
|
||||
}
|
||||
|
||||
@@ -194,10 +194,6 @@ export type ViewsState = {
|
||||
lastSelectedChannel: string;
|
||||
};
|
||||
|
||||
addChannelDropdown: {
|
||||
isOpen: boolean;
|
||||
};
|
||||
|
||||
addChannelCtaDropdown: {
|
||||
isOpen: boolean;
|
||||
};
|
||||
|
||||
@@ -250,7 +250,6 @@ export const ActionTypes = keyMirror({
|
||||
INCREMENT_EMOJI_PICKER_PAGE: null,
|
||||
SET_RECENT_SKIN: null,
|
||||
|
||||
ADD_CHANNEL_DROPDOWN_TOGGLE: null,
|
||||
ADD_CHANNEL_CTA_DROPDOWN_TOGGLE: null,
|
||||
|
||||
SHOW_ONBOARDING_TASK_COMPLETION: null,
|
||||
|
||||
@@ -33,20 +33,3 @@ export function isKeyPressed(event: React.KeyboardEvent | KeyboardEvent, key: [s
|
||||
// used for different language keyboards to detect the position of keys
|
||||
return event.keyCode === key[1];
|
||||
}
|
||||
|
||||
export const MenuButtonIds = {
|
||||
userAccountMenu: 'userAccountMenuButton',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Since the menu component requires actual interaction with the button
|
||||
* of the menu for opening the menus, we trigger it from here
|
||||
*/
|
||||
export function clickOnMenuButton(buttonId: string) {
|
||||
const menuButton = document.getElementById(buttonId);
|
||||
if (!menuButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
menuButton.click();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
$z-index-tour-tips-backdrop: 1250;
|
||||
|
||||
.tour-tip {
|
||||
display: flex;
|
||||
|
||||
@@ -222,7 +224,6 @@
|
||||
|
||||
&__overlay {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
@@ -357,7 +358,7 @@
|
||||
|
||||
&__backdrop {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
z-index: $z-index-tour-tips-backdrop;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
@@ -21,6 +21,9 @@ import './tour_tip.scss';
|
||||
|
||||
export type TourTipEventSource = 'next' | 'prev' | 'dismiss' | 'jump' | 'skipped' | 'open' | 'punchOut'
|
||||
|
||||
// If this needs to alter, change in _variables $z-index-tour-tips-popover as well
|
||||
const DEFAULT_Z_INDEX_TOUR_TIPS_POPOVER = 1300;
|
||||
|
||||
type Props = {
|
||||
show: boolean;
|
||||
screen: JSX.Element;
|
||||
@@ -84,7 +87,7 @@ export const TourTip = ({
|
||||
placement = 'right-start',
|
||||
showOptOut = true,
|
||||
width = 352,
|
||||
zIndex = 999,
|
||||
zIndex = DEFAULT_Z_INDEX_TOUR_TIPS_POPOVER,
|
||||
hideBackdrop = false,
|
||||
tippyBlueStyle = false,
|
||||
}: Props) => {
|
||||
|
||||
Ссылка в новой задаче
Block a user