MM-46494: Add filter options to browse channel modal (#24099)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c9d49536f8
Коммит
53fc44e13a
@@ -16,6 +16,7 @@ describe('Leave an archived channel', () => {
|
|||||||
let testTeam;
|
let testTeam;
|
||||||
let offTopicUrl;
|
let offTopicUrl;
|
||||||
const channelType = {
|
const channelType = {
|
||||||
|
all: 'Channel Type: All',
|
||||||
public: 'Channel Type: Public',
|
public: 'Channel Type: Public',
|
||||||
archived: 'Channel Type: Archived',
|
archived: 'Channel Type: Archived',
|
||||||
};
|
};
|
||||||
@@ -98,19 +99,18 @@ describe('Leave an archived channel', () => {
|
|||||||
cy.get('#showMoreChannels').click();
|
cy.get('#showMoreChannels').click();
|
||||||
|
|
||||||
// # More channels modal opens
|
// # More channels modal opens
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible');
|
||||||
// # Click on dropdown
|
|
||||||
cy.findByText(channelType.public).should('be.visible').click();
|
|
||||||
|
|
||||||
// # Click archived channels
|
// # Click on dropdown
|
||||||
cy.findByText('Archived Channels').click();
|
cy.findByText(channelType.all).should('be.visible').click();
|
||||||
|
|
||||||
// # Modal should contain created channel
|
// # Click archived channels
|
||||||
cy.get('#moreChannelsList').should('contain', channel.display_name);
|
cy.findByText('Archived channels').click();
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('body').typeWithForce('{esc}');
|
// # Modal should contain created channel
|
||||||
|
cy.get('#moreChannelsList').should('contain', channel.display_name);
|
||||||
});
|
});
|
||||||
|
cy.get('body').typeWithForce('{esc}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T1699 - Browse Channels for all channel types shows archived channels option', () => {
|
it('MM-T1699 - Browse Channels for all channel types shows archived channels option', () => {
|
||||||
@@ -146,12 +146,12 @@ describe('Leave an archived channel', () => {
|
|||||||
cy.get('#showMoreChannels').click();
|
cy.get('#showMoreChannels').click();
|
||||||
|
|
||||||
// # More channels modal opens
|
// # More channels modal opens
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||||
// # Public channel list opens by default
|
// # All channel list opens by default
|
||||||
cy.findByText(channelType.public).should('be.visible').click();
|
cy.findByText(channelType.all).should('be.visible').click();
|
||||||
|
|
||||||
// # Click on archived channels
|
// # Click on archived channels
|
||||||
cy.findByText('Archived Channels').click();
|
cy.findByText('Archived channels').click();
|
||||||
|
|
||||||
// # Channel list should contain newly created channels
|
// # Channel list should contain newly created channels
|
||||||
cy.get('#moreChannelsList').should('contain', archivedPrivateChannel.name);
|
cy.get('#moreChannelsList').should('contain', archivedPrivateChannel.name);
|
||||||
@@ -199,12 +199,12 @@ describe('Leave an archived channel', () => {
|
|||||||
cy.get('#showMoreChannels').click();
|
cy.get('#showMoreChannels').click();
|
||||||
|
|
||||||
// # More channels modal opens
|
// # More channels modal opens
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||||
// # Public channels are shown by default
|
// # All channels are shown by default
|
||||||
cy.findByText(channelType.public).should('be.visible').click();
|
cy.findByText(channelType.all).should('be.visible').click();
|
||||||
|
|
||||||
// # Go to archived channels
|
// # Go to archived channels
|
||||||
cy.findByText('Archived Channels').click();
|
cy.findByText('Archived channels').click();
|
||||||
|
|
||||||
// # Channel list should contain both archived public channels
|
// # Channel list should contain both archived public channels
|
||||||
cy.get('#moreChannelsList').should('contain', archivedPublicChannel1.display_name);
|
cy.get('#moreChannelsList').should('contain', archivedPublicChannel1.display_name);
|
||||||
@@ -253,12 +253,12 @@ describe('Leave an archived channel', () => {
|
|||||||
cy.get('#showMoreChannels').click();
|
cy.get('#showMoreChannels').click();
|
||||||
|
|
||||||
// # More channels modal opens
|
// # More channels modal opens
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||||
// # Show public channels is visible by default
|
// # Show all channels is visible by default
|
||||||
cy.findByText(channelType.public).should('be.visible').click();
|
cy.findByText(channelType.all).should('be.visible').click();
|
||||||
|
|
||||||
// # Go to archived channels
|
// # Go to archived channels
|
||||||
cy.findByText('Archived Channels').click();
|
cy.findByText('Archived channels').click();
|
||||||
|
|
||||||
// # Channel list should contain only the private channel user is a member of
|
// # Channel list should contain only the private channel user is a member of
|
||||||
cy.get('#moreChannelsList').should('contain', archivedPrivateChannel1.name);
|
cy.get('#moreChannelsList').should('contain', archivedPrivateChannel1.name);
|
||||||
@@ -287,12 +287,12 @@ describe('Leave an archived channel', () => {
|
|||||||
// # Click on browse channels
|
// # Click on browse channels
|
||||||
cy.get('#showMoreChannels').click();
|
cy.get('#showMoreChannels').click();
|
||||||
|
|
||||||
// # More channels modal opens and lands on public channels
|
// # More channels modal opens and lands on all channels
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible').then(() => {
|
||||||
cy.findByText(channelType.public).should('be.visible').click();
|
cy.findByText(channelType.all).should('be.visible').click();
|
||||||
|
|
||||||
// # Go to archived channels
|
// # Go to archived channels
|
||||||
cy.findByText('Archived Channels').click();
|
cy.findByText('Archived channels').click();
|
||||||
|
|
||||||
// # More channels list should contain the archived channel
|
// # More channels list should contain the archived channel
|
||||||
cy.get('#moreChannelsList').should('contain', archivedChannel.display_name);
|
cy.get('#moreChannelsList').should('contain', archivedChannel.display_name);
|
||||||
@@ -323,7 +323,8 @@ describe('Leave an archived channel', () => {
|
|||||||
cy.get('#showMoreChannels').click();
|
cy.get('#showMoreChannels').click();
|
||||||
|
|
||||||
// # Modal should not contain the created channel
|
// # Modal should not contain the created channel
|
||||||
cy.get('#channelsMoreDropdown').should('not.exist');
|
cy.findByText(channelType.all).should('be.visible').click();
|
||||||
|
cy.findByText('Archived channels').should('not.exist');
|
||||||
cy.get('#moreChannelsList').should('not.contain', channel.name);
|
cy.get('#moreChannelsList').should('not.contain', channel.name);
|
||||||
});
|
});
|
||||||
cy.get('body').typeWithForce('{esc}');
|
cy.get('body').typeWithForce('{esc}');
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import * as TIMEOUTS from '../../../fixtures/timeouts';
|
|||||||
import {createPrivateChannel} from '../enterprise/elasticsearch_autocomplete/helpers';
|
import {createPrivateChannel} from '../enterprise/elasticsearch_autocomplete/helpers';
|
||||||
|
|
||||||
const channelType = {
|
const channelType = {
|
||||||
|
all: 'Channel Type: All',
|
||||||
public: 'Channel Type: Public',
|
public: 'Channel Type: Public',
|
||||||
archived: 'Channel Type: Archived',
|
archived: 'Channel Type: Archived',
|
||||||
};
|
};
|
||||||
@@ -69,8 +70,8 @@ describe('Channels', () => {
|
|||||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||||
|
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
||||||
// * Dropdown should be visible, defaulting to "Public Channels"
|
// * Dropdown should be visible, defaulting to "All Channels"
|
||||||
cy.get('#channelsMoreDropdown').should('be.visible').and('contain', channelType.public).wait(TIMEOUTS.HALF_SEC);
|
cy.get('#menuWrapper').should('be.visible').and('contain', channelType.all).wait(TIMEOUTS.HALF_SEC);
|
||||||
|
|
||||||
cy.get('#searchChannelsTextbox').should('be.visible').type(testChannel.display_name).wait(TIMEOUTS.HALF_SEC);
|
cy.get('#searchChannelsTextbox').should('be.visible').type(testChannel.display_name).wait(TIMEOUTS.HALF_SEC);
|
||||||
cy.get('#moreChannelsList').should('be.visible').children().should('have.length', 1).within(() => {
|
cy.get('#moreChannelsList').should('be.visible').children().should('have.length', 1).within(() => {
|
||||||
@@ -111,27 +112,27 @@ describe('Channels', () => {
|
|||||||
// # Go to LHS and click 'Browse channels'
|
// # Go to LHS and click 'Browse channels'
|
||||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||||
|
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible');
|
||||||
// # CLick dropdown to open selection
|
|
||||||
cy.get('#channelsMoreDropdown').should('be.visible').click().within((el) => {
|
|
||||||
// # Click on archived channels item
|
|
||||||
cy.findByText('Archived Channels').should('be.visible').click();
|
|
||||||
|
|
||||||
// * Channel test should be visible as an archived channel in the list
|
// # CLick dropdown to open selection
|
||||||
cy.wrap(el).should('contain', channelType.archived);
|
cy.get('#menuWrapper').should('be.visible').click();
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('#searchChannelsTextbox').should('be.visible').type(testChannel.display_name).wait(TIMEOUTS.HALF_SEC);
|
// # Click on archived channels item
|
||||||
cy.get('#moreChannelsList').children().should('have.length', 1).within(() => {
|
cy.findByText('Archived channels').should('be.visible').click();
|
||||||
cy.findByText(testChannel.display_name).should('be.visible');
|
|
||||||
});
|
|
||||||
cy.get('#searchChannelsTextbox').clear();
|
|
||||||
|
|
||||||
// * Test channel should be visible as a archived channel in the list
|
// * Menu text should be updated to reflect the selection
|
||||||
cy.get('#moreChannelsList').should('be.visible').within(() => {
|
cy.get('#menuWrapper').should('contain', channelType.archived);
|
||||||
// # Click to view archived channel
|
|
||||||
cy.findByText(testChannel.display_name).scrollIntoView().should('be.visible').click();
|
cy.get('#searchChannelsTextbox').should('be.visible').type(testChannel.display_name).wait(TIMEOUTS.HALF_SEC);
|
||||||
});
|
cy.get('#moreChannelsList').children().should('have.length', 1).within(() => {
|
||||||
|
cy.findByText(testChannel.display_name).should('be.visible');
|
||||||
|
});
|
||||||
|
cy.get('#searchChannelsTextbox').clear();
|
||||||
|
|
||||||
|
// * Test channel should be visible as a archived channel in the list
|
||||||
|
cy.get('#moreChannelsList').should('be.visible').within(() => {
|
||||||
|
// # Click to view archived channel
|
||||||
|
cy.findByText(testChannel.display_name).scrollIntoView().should('be.visible').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
// * Assert that channel is archived and new messages can't be posted.
|
// * Assert that channel is archived and new messages can't be posted.
|
||||||
@@ -177,7 +178,7 @@ describe('Channels', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T1702 Search works when changing public/archived options in the dropdown', () => {
|
it('MM-T1702 Search works when changing public/all options in the dropdown', () => {
|
||||||
cy.apiAdminLogin();
|
cy.apiAdminLogin();
|
||||||
cy.apiUpdateConfig({
|
cy.apiUpdateConfig({
|
||||||
TeamSettings: {
|
TeamSettings: {
|
||||||
@@ -231,32 +232,34 @@ describe('Channels', () => {
|
|||||||
// # Go to LHS and click 'Browse channels'
|
// # Go to LHS and click 'Browse channels'
|
||||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||||
|
|
||||||
// * Dropdown should be visible, defaulting to "Public Channels"
|
// * Dropdown should be visible, defaulting to "All channels"
|
||||||
cy.get('#channelsMoreDropdown').should('be.visible').within((el) => {
|
cy.get('#menuWrapper').should('be.visible').within((el) => {
|
||||||
cy.wrap(el).should('contain', channelType.public);
|
cy.wrap(el).should('contain', channelType.all);
|
||||||
});
|
});
|
||||||
|
|
||||||
// * Users should be able to type and search
|
// * Users should be able to type and search
|
||||||
cy.get('#searchChannelsTextbox').should('be.visible').type('iv').wait(TIMEOUTS.HALF_SEC);
|
cy.get('#searchChannelsTextbox').should('be.visible').type('iv').wait(TIMEOUTS.HALF_SEC);
|
||||||
cy.get('#moreChannelsList').should('be.visible').children().should('have.length', 1).within(() => {
|
cy.get('#moreChannelsList').should('be.visible').children().should('have.length', 2);
|
||||||
|
cy.get('#moreChannelsList').should('be.visible').within(() => {
|
||||||
cy.findByText(newChannel.display_name).should('be.visible');
|
cy.findByText(newChannel.display_name).should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
cy.get('#browseChannelsModal').should('be.visible');
|
||||||
// * Users should be able to switch to "Archived Channels" list
|
|
||||||
cy.get('#channelsMoreDropdown').should('be.visible').and('contain', channelType.public).click().within((el) => {
|
|
||||||
// # Click on archived channels item
|
|
||||||
cy.findByText('Archived Channels').should('be.visible').click();
|
|
||||||
|
|
||||||
// * Modal should show the archived channels list
|
// * Users should be able to switch to "Archived Channels" list
|
||||||
cy.wrap(el).should('contain', channelType.archived);
|
cy.get('#menuWrapper').should('be.visible').and('contain', channelType.all).click().wait(TIMEOUTS.HALF_SEC);
|
||||||
}).wait(TIMEOUTS.HALF_SEC);
|
|
||||||
cy.get('#searchChannelsTextbox').clear();
|
// # Click on archived channels item
|
||||||
cy.get('#moreChannelsList').should('be.visible').children().should('have.length', 2);
|
cy.findByText('Archived channels').should('be.visible').click();
|
||||||
cy.get('#moreChannelsList').within(() => {
|
|
||||||
cy.findByText(testArchivedChannel.display_name).should('be.visible');
|
// * Modal menu should be updated accordingly
|
||||||
cy.findByText(testPrivateArchivedChannel.display_name).should('be.visible');
|
cy.get('#menuWrapper').should('contain', channelType.archived);
|
||||||
});
|
|
||||||
|
cy.get('#searchChannelsTextbox').clear();
|
||||||
|
cy.get('#moreChannelsList').should('be.visible').children().should('have.length', 2);
|
||||||
|
cy.get('#moreChannelsList').within(() => {
|
||||||
|
cy.findByText(testArchivedChannel.display_name).should('be.visible');
|
||||||
|
cy.findByText(testPrivateArchivedChannel.display_name).should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -287,9 +290,10 @@ function verifyBrowseChannelsModal(isEnabled) {
|
|||||||
// * Verify that the browse channels modal is open and with or without option to view archived 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(() => {
|
cy.get('#browseChannelsModal').should('be.visible').within(() => {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
cy.get('#channelsMoreDropdown').should('be.visible').and('have.text', channelType.public);
|
cy.get('#menuWrapper').should('be.visible').and('have.text', channelType.all);
|
||||||
} else {
|
} else {
|
||||||
cy.get('#channelsMoreDropdown').should('not.exist');
|
cy.get('#menuWrapper').click();
|
||||||
|
cy.findByText('Archived channels').should('not.exist');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ function verifyNoChannelToJoinMessage(isVisible) {
|
|||||||
cy.findByText('No public channels').should(isVisible ? 'be.visible' : 'not.exist');
|
cy.findByText('No public channels').should(isVisible ? 'be.visible' : 'not.exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('more public channels', () => {
|
describe('browse public channels', () => {
|
||||||
let testUser;
|
let testUser;
|
||||||
let otherUser;
|
let otherUser;
|
||||||
let testTeam;
|
let testTeam;
|
||||||
@@ -41,7 +41,7 @@ describe('more public channels', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T1664 Channels do not disappear from More Channels modal', () => {
|
it('MM-T1664 Channels do not disappear from Browse Channels modal', () => {
|
||||||
// # Login as other user
|
// # Login as other user
|
||||||
cy.apiLogin(otherUser);
|
cy.apiLogin(otherUser);
|
||||||
|
|
||||||
@@ -51,8 +51,14 @@ describe('more public channels', () => {
|
|||||||
// # Go to LHS and click 'Browse channels'
|
// # Go to LHS and click 'Browse channels'
|
||||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||||
|
|
||||||
// * Assert that the moreChannelsModel is visible
|
// * Assert that the browse channel modal is visible
|
||||||
cy.findByRole('dialog', {name: 'Browse Channels'}).should('be.visible').within(() => {
|
cy.findByRole('dialog', {name: 'Browse Channels'}).should('be.visible').then(() => {
|
||||||
|
// # Click on dropdown
|
||||||
|
cy.findByText('Channel Type: All').should('be.visible').click();
|
||||||
|
|
||||||
|
// # Click archived channels
|
||||||
|
cy.findByText('Public channels').should('be.visible').click();
|
||||||
|
|
||||||
// # Click hide joined checkbox if not already checked
|
// # Click hide joined checkbox if not already checked
|
||||||
cy.findByText('Hide Joined').should('be.visible').then(($checkbox) => {
|
cy.findByText('Hide Joined').should('be.visible').then(($checkbox) => {
|
||||||
if (!$checkbox.prop('checked')) {
|
if (!$checkbox.prop('checked')) {
|
||||||
@@ -92,7 +98,13 @@ describe('more public channels', () => {
|
|||||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||||
|
|
||||||
// * Assert the moreChannelsModel is visible
|
// * Assert the moreChannelsModel is visible
|
||||||
cy.findByRole('dialog', {name: 'Browse Channels'}).should('be.visible').within(() => {
|
cy.findByRole('dialog', {name: 'Browse Channels'}).should('be.visible').then(() => {
|
||||||
|
// # Click on dropdown
|
||||||
|
cy.findByText('Channel Type: All').should('be.visible').click();
|
||||||
|
|
||||||
|
// # Click archived channels
|
||||||
|
cy.findByText('Public channels').should('be.visible').click();
|
||||||
|
|
||||||
// * Assert that the "No more channels to join" message is visible
|
// * Assert that the "No more channels to join" message is visible
|
||||||
verifyNoChannelToJoinMessage(true);
|
verifyNoChannelToJoinMessage(true);
|
||||||
});
|
});
|
||||||
@@ -86,7 +86,7 @@ describe('Verify Accessibility Support in Modals & Dialogs', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T1467 Accessibility Support in More Channels Dialog screen', () => {
|
it('MM-T1467 Accessibility Support in Browse Channels Dialog screen', () => {
|
||||||
function getChannelAriaLabel(channel) {
|
function getChannelAriaLabel(channel) {
|
||||||
return channel.display_name.toLowerCase() + ', ' + channel.purpose.toLowerCase();
|
return channel.display_name.toLowerCase() + ', ' + channel.purpose.toLowerCase();
|
||||||
}
|
}
|
||||||
@@ -117,8 +117,8 @@ describe('Verify Accessibility Support in Modals & Dialogs', () => {
|
|||||||
// # Hide already joined channels
|
// # Hide already joined channels
|
||||||
cy.findByText('Hide Joined').click();
|
cy.findByText('Hide Joined').click();
|
||||||
|
|
||||||
// # Focus on the Create Channel button and TAB three time
|
// # Focus on the Create Channel button and TAB four time
|
||||||
cy.get('#createNewChannelButton').focus().tab().tab().tab();
|
cy.get('#createNewChannelButton').focus().tab().tab().tab().tab();
|
||||||
|
|
||||||
// * Verify channel name is highlighted and reader reads the channel name and channel description
|
// * Verify channel name is highlighted and reader reads the channel name and channel description
|
||||||
cy.get('#moreChannelsList').within(() => {
|
cy.get('#moreChannelsList').within(() => {
|
||||||
|
|||||||
@@ -232,9 +232,9 @@ context('ldap', () => {
|
|||||||
cy.visit(`/${testTeam.name}`);
|
cy.visit(`/${testTeam.name}`);
|
||||||
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
cy.uiBrowseOrCreateChannel('Browse channels').click();
|
||||||
|
|
||||||
// * Search private channel name and make sure it isn't there in public channel directory
|
// * Search private channel name and make sure it is still visible
|
||||||
cy.get('#searchChannelsTextbox').type(testChannel.display_name);
|
cy.get('#searchChannelsTextbox').type(testChannel.display_name);
|
||||||
cy.get('#moreChannelsList').should('include.text', 'No results for');
|
cy.get('#moreChannelsList').should('include.text', testChannel.display_name);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T2629 - Private to public - More....', () => {
|
it('MM-T2629 - Private to public - More....', () => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"@guyplusplus/turndown-plugin-gfm": "1.0.7",
|
"@guyplusplus/turndown-plugin-gfm": "1.0.7",
|
||||||
"@mattermost/client": "*",
|
"@mattermost/client": "*",
|
||||||
"@mattermost/compass-components": "^0.2.12",
|
"@mattermost/compass-components": "^0.2.12",
|
||||||
"@mattermost/compass-icons": "0.1.34",
|
"@mattermost/compass-icons": "0.1.37",
|
||||||
"@mattermost/types": "*",
|
"@mattermost/types": "*",
|
||||||
"@mui/base": "5.0.0-alpha.127",
|
"@mui/base": "5.0.0-alpha.127",
|
||||||
"@mui/material": "5.11.16",
|
"@mui/material": "5.11.16",
|
||||||
|
|||||||
@@ -48,6 +48,89 @@ exports[`components/SearchableChannelList should match init snapshot 1`] = `
|
|||||||
<div
|
<div
|
||||||
id="modalPreferenceContainer"
|
id="modalPreferenceContainer"
|
||||||
>
|
>
|
||||||
|
<Menu
|
||||||
|
menu={
|
||||||
|
Object {
|
||||||
|
"aria-label": "Browse channels",
|
||||||
|
"id": "browseChannelsDropdown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menuButton={
|
||||||
|
Object {
|
||||||
|
"children": <React.Fragment>
|
||||||
|
<Memo(MemoizedFormattedMessage)
|
||||||
|
defaultMessage="Channel Type: All"
|
||||||
|
id="more_channels.show_all_channels"
|
||||||
|
/>
|
||||||
|
<ChevronDownIcon
|
||||||
|
color="rgba(var(--center-channel-color-rgb), 0.64)"
|
||||||
|
size={16}
|
||||||
|
/>
|
||||||
|
</React.Fragment>,
|
||||||
|
"id": "menuWrapper",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
aria-label="All channel types"
|
||||||
|
id="channelsMoreDropdownAll"
|
||||||
|
key="channelsMoreDropdownAll"
|
||||||
|
labels={
|
||||||
|
<Memo(MemoizedFormattedMessage)
|
||||||
|
defaultMessage="All channel types"
|
||||||
|
id="suggestion.all"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
leadingElement={
|
||||||
|
<GlobeCheckedIcon
|
||||||
|
size={16}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onClick={[Function]}
|
||||||
|
trailingElements={
|
||||||
|
<CheckIcon
|
||||||
|
color="var(--button-bg)"
|
||||||
|
size={18}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
aria-label="Public channels"
|
||||||
|
id="channelsMoreDropdownPublic"
|
||||||
|
key="channelsMoreDropdownPublic"
|
||||||
|
labels={
|
||||||
|
<Memo(MemoizedFormattedMessage)
|
||||||
|
defaultMessage="Public channels"
|
||||||
|
id="suggestion.public"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
leadingElement={
|
||||||
|
<GlobeIcon
|
||||||
|
size={16}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onClick={[Function]}
|
||||||
|
trailingElements={null}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
aria-label="Private channels"
|
||||||
|
id="channelsMoreDropdownPrivate"
|
||||||
|
key="channelsMoreDropdownPrivate"
|
||||||
|
labels={
|
||||||
|
<Memo(MemoizedFormattedMessage)
|
||||||
|
defaultMessage="Private channels"
|
||||||
|
id="suggestion.private"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
leadingElement={
|
||||||
|
<LockOutlineIcon
|
||||||
|
size={16}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onClick={[Function]}
|
||||||
|
trailingElements={null}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
<div
|
<div
|
||||||
id="hideJoinedPreferenceCheckbox"
|
id="hideJoinedPreferenceCheckbox"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ exports[`components/BrowseChannels should match snapshot and state 1`] = `
|
|||||||
"create_public_channel",
|
"create_public_channel",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
teamId="team_id"
|
teamId="team_1"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Create New Channel"
|
aria-label="Create New Channel"
|
||||||
@@ -45,8 +45,26 @@ exports[`components/BrowseChannels should match snapshot and state 1`] = `
|
|||||||
>
|
>
|
||||||
<SearchableChannelList
|
<SearchableChannelList
|
||||||
canShowArchivedChannels={true}
|
canShowArchivedChannels={true}
|
||||||
|
changeFilter={[Function]}
|
||||||
channels={
|
channels={
|
||||||
Array [
|
Array [
|
||||||
|
Object {
|
||||||
|
"create_at": 0,
|
||||||
|
"creator_id": "id",
|
||||||
|
"delete_at": 0,
|
||||||
|
"display_name": "channel-3",
|
||||||
|
"group_constrained": false,
|
||||||
|
"header": "channel-3-header",
|
||||||
|
"id": "channel_id_3",
|
||||||
|
"last_post_at": 0,
|
||||||
|
"last_root_post_at": 0,
|
||||||
|
"name": "channel-3",
|
||||||
|
"purpose": "channel-3-purpose",
|
||||||
|
"scheme_id": "id",
|
||||||
|
"team_id": "team_1",
|
||||||
|
"type": "P",
|
||||||
|
"update_at": 0,
|
||||||
|
},
|
||||||
Object {
|
Object {
|
||||||
"create_at": 0,
|
"create_at": 0,
|
||||||
"creator_id": "id",
|
"creator_id": "id",
|
||||||
@@ -68,11 +86,37 @@ exports[`components/BrowseChannels should match snapshot and state 1`] = `
|
|||||||
}
|
}
|
||||||
channelsPerPage={50}
|
channelsPerPage={50}
|
||||||
closeModal={[MockFunction]}
|
closeModal={[MockFunction]}
|
||||||
|
filter="All"
|
||||||
handleJoin={[Function]}
|
handleJoin={[Function]}
|
||||||
hideJoinedChannelsPreference={[Function]}
|
hideJoinedChannelsPreference={[Function]}
|
||||||
isSearch={false}
|
isSearch={false}
|
||||||
loading={false}
|
loading={false}
|
||||||
myChannelMemberships={Object {}}
|
myChannelMemberships={
|
||||||
|
Object {
|
||||||
|
"channel-id-3": Object {
|
||||||
|
"channel_id": "channel-id-3",
|
||||||
|
"last_update_at": 0,
|
||||||
|
"last_viewed_at": 0,
|
||||||
|
"mention_count": 0,
|
||||||
|
"mention_count_root": 0,
|
||||||
|
"msg_count": 0,
|
||||||
|
"msg_count_root": 0,
|
||||||
|
"notify_props": Object {
|
||||||
|
"channel_auto_follow_threads": "off",
|
||||||
|
"desktop": "default",
|
||||||
|
"email": "default",
|
||||||
|
"ignore_channel_mentions": "default",
|
||||||
|
"mark_unread": "all",
|
||||||
|
"push": "default",
|
||||||
|
},
|
||||||
|
"roles": "channel_user",
|
||||||
|
"scheme_admin": false,
|
||||||
|
"scheme_user": true,
|
||||||
|
"urgent_mention_count": 0,
|
||||||
|
"user_id": "user-1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
nextPage={[Function]}
|
nextPage={[Function]}
|
||||||
noResultsText={
|
noResultsText={
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@@ -90,7 +134,7 @@ exports[`components/BrowseChannels should match snapshot and state 1`] = `
|
|||||||
"create_public_channel",
|
"create_public_channel",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
teamId="team_id"
|
teamId="team_1"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Create New Channel"
|
aria-label="Create New Channel"
|
||||||
@@ -112,8 +156,6 @@ exports[`components/BrowseChannels should match snapshot and state 1`] = `
|
|||||||
}
|
}
|
||||||
rememberHideJoinedChannelsChecked={false}
|
rememberHideJoinedChannelsChecked={false}
|
||||||
search={[Function]}
|
search={[Function]}
|
||||||
shouldShowArchivedChannels={false}
|
|
||||||
toggleArchivedChannels={[Function]}
|
|
||||||
/>
|
/>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -58,23 +58,6 @@
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.MenuItem__primary-text {
|
|
||||||
width: 100%;
|
|
||||||
color: var(--center-channel-color);
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 20px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Menu__content {
|
|
||||||
border-color: rgba(var(--center-channel-color-rgb), 0.16);
|
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
#channelCountLabel {
|
#channelCountLabel {
|
||||||
color: var(--center-channel-color);
|
color: var(--center-channel-color);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -100,32 +83,25 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#channelsMoreDropdown {
|
|
||||||
margin: 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menuWrapper {
|
#menuWrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 4px 6px 4px 8px;
|
padding: 4px 6px 4px 8px;
|
||||||
border: none;
|
border: none;
|
||||||
|
margin-right: 10px;
|
||||||
background-color: unset;
|
background-color: unset;
|
||||||
|
|
||||||
|
&[aria-expanded='true'] {
|
||||||
|
background-color: rgba(var(--button-bg-rgb), 0.12);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.MenuWrapper:hover {
|
#menuWrapper:hover {
|
||||||
background-color: rgba(var(--center-channel-color-rgb), 0.08);
|
background-color: rgba(var(--center-channel-color-rgb), 0.08);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.MenuWrapper--open {
|
|
||||||
background-color: rgba(var(--button-bg-rgb), 0.12);
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(var(--button-bg-rgb), 0.12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,3 +271,11 @@
|
|||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#browseChannelsDropdown {
|
||||||
|
.label-elements {
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {shallow} from 'enzyme';
|
|||||||
import {ActionResult} from 'mattermost-redux/types/actions';
|
import {ActionResult} from 'mattermost-redux/types/actions';
|
||||||
import {Channel} from '@mattermost/types/channels';
|
import {Channel} from '@mattermost/types/channels';
|
||||||
|
|
||||||
import BrowseChannels, {Props} from 'components/browse_channels/browse_channels';
|
import BrowseChannels, {Filter, Props} from 'components/browse_channels/browse_channels';
|
||||||
import SearchableChannelList from 'components/searchable_channel_list';
|
import SearchableChannelList from 'components/searchable_channel_list';
|
||||||
|
|
||||||
import {getHistory} from 'utils/browser_history';
|
import {getHistory} from 'utils/browser_history';
|
||||||
@@ -20,25 +20,53 @@ describe('components/BrowseChannels', () => {
|
|||||||
data: [{
|
data: [{
|
||||||
id: 'channel-id-1',
|
id: 'channel-id-1',
|
||||||
name: 'channel-name-1',
|
name: 'channel-name-1',
|
||||||
|
team_id: 'team_1',
|
||||||
display_name: 'Channel 1',
|
display_name: 'Channel 1',
|
||||||
delete_at: 0,
|
delete_at: 0,
|
||||||
|
type: 'O',
|
||||||
}, {
|
}, {
|
||||||
id: 'channel-id-2',
|
id: 'channel-id-2',
|
||||||
name: 'archived-channel',
|
name: 'archived-channel',
|
||||||
|
team_id: 'team_1',
|
||||||
display_name: 'Archived',
|
display_name: 'Archived',
|
||||||
delete_at: 123,
|
delete_at: 123,
|
||||||
|
type: 'O',
|
||||||
|
}, {
|
||||||
|
id: 'channel-id-3',
|
||||||
|
name: 'private-channel',
|
||||||
|
team_id: 'team_1',
|
||||||
|
display_name: 'Private',
|
||||||
|
delete_at: 0,
|
||||||
|
type: 'P',
|
||||||
|
}, {
|
||||||
|
id: 'channel-id-4',
|
||||||
|
name: 'private-channel-not-member',
|
||||||
|
team_id: 'team_1',
|
||||||
|
display_name: 'Private Not Member',
|
||||||
|
delete_at: 0,
|
||||||
|
type: 'P',
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|
||||||
const archivedChannel = TestHelper.getChannelMock({
|
const archivedChannel = TestHelper.getChannelMock({
|
||||||
id: 'channel_id_2',
|
id: 'channel_id_2',
|
||||||
team_id: 'channel_team_2',
|
team_id: 'team_1',
|
||||||
display_name: 'channel-2',
|
display_name: 'channel-2',
|
||||||
name: 'channel-2',
|
name: 'channel-2',
|
||||||
header: 'channel-2-header',
|
header: 'channel-2-header',
|
||||||
purpose: 'channel-2-purpose',
|
purpose: 'channel-2-purpose',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const privateChannel = TestHelper.getChannelMock({
|
||||||
|
id: 'channel_id_3',
|
||||||
|
team_id: 'team_1',
|
||||||
|
display_name: 'channel-3',
|
||||||
|
name: 'channel-3',
|
||||||
|
header: 'channel-3-header',
|
||||||
|
purpose: 'channel-3-purpose',
|
||||||
|
type: 'P',
|
||||||
|
});
|
||||||
|
|
||||||
const channelActions = {
|
const channelActions = {
|
||||||
joinChannelAction: (userId: string, teamId: string, channelId: string): Promise<ActionResult> => {
|
joinChannelAction: (userId: string, teamId: string, channelId: string): Promise<ActionResult> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@@ -53,7 +81,7 @@ describe('components/BrowseChannels', () => {
|
|||||||
return resolve({data: true});
|
return resolve({data: true});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
searchMoreChannels: (term: string): Promise<ActionResult> => {
|
searchAllChannels: (term: string): Promise<ActionResult> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
if (term === 'fail') {
|
if (term === 'fail') {
|
||||||
return resolve({
|
return resolve({
|
||||||
@@ -85,18 +113,24 @@ describe('components/BrowseChannels', () => {
|
|||||||
const baseProps: Props = {
|
const baseProps: Props = {
|
||||||
channels: [TestHelper.getChannelMock({})],
|
channels: [TestHelper.getChannelMock({})],
|
||||||
archivedChannels: [archivedChannel],
|
archivedChannels: [archivedChannel],
|
||||||
|
privateChannels: [privateChannel],
|
||||||
currentUserId: 'user-1',
|
currentUserId: 'user-1',
|
||||||
teamId: 'team_id',
|
teamId: 'team_1',
|
||||||
teamName: 'team_name',
|
teamName: 'team_name',
|
||||||
channelsRequestStarted: false,
|
channelsRequestStarted: false,
|
||||||
canShowArchivedChannels: true,
|
canShowArchivedChannels: true,
|
||||||
shouldHideJoinedChannels: false,
|
shouldHideJoinedChannels: false,
|
||||||
myChannelMemberships: {},
|
myChannelMemberships: {
|
||||||
|
'channel-id-3': TestHelper.getChannelMembershipMock({
|
||||||
|
channel_id: 'channel-id-3',
|
||||||
|
user_id: 'user-1',
|
||||||
|
}),
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
getChannels: jest.fn(channelActions.getChannels),
|
getChannels: jest.fn(channelActions.getChannels),
|
||||||
getArchivedChannels: jest.fn(channelActions.getArchivedChannels),
|
getArchivedChannels: jest.fn(channelActions.getArchivedChannels),
|
||||||
joinChannel: jest.fn(channelActions.joinChannelAction),
|
joinChannel: jest.fn(channelActions.joinChannelAction),
|
||||||
searchMoreChannels: jest.fn(channelActions.searchMoreChannels),
|
searchAllChannels: jest.fn(channelActions.searchAllChannels),
|
||||||
openModal: jest.fn(),
|
openModal: jest.fn(),
|
||||||
closeModal: jest.fn(),
|
closeModal: jest.fn(),
|
||||||
closeRightHandSide: jest.fn(),
|
closeRightHandSide: jest.fn(),
|
||||||
@@ -112,7 +146,6 @@ describe('components/BrowseChannels', () => {
|
|||||||
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
expect(wrapper.state('searchedChannels')).toEqual([]);
|
expect(wrapper.state('searchedChannels')).toEqual([]);
|
||||||
expect(wrapper.state('shouldShowArchivedChannels')).toEqual(false);
|
|
||||||
expect(wrapper.state('search')).toEqual(false);
|
expect(wrapper.state('search')).toEqual(false);
|
||||||
expect(wrapper.state('serverError')).toBeNull();
|
expect(wrapper.state('serverError')).toBeNull();
|
||||||
expect(wrapper.state('searching')).toEqual(false);
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
@@ -257,8 +290,8 @@ describe('components/BrowseChannels', () => {
|
|||||||
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
||||||
|
|
||||||
jest.runOnlyPendingTimers();
|
jest.runOnlyPendingTimers();
|
||||||
expect(wrapper.instance().props.actions.searchMoreChannels).toHaveBeenCalledTimes(1);
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledTimes(1);
|
||||||
expect(wrapper.instance().props.actions.searchMoreChannels).toHaveBeenCalledWith('fail', false, false);
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledWith('fail', {include_deleted: true, nonAdminSearch: true, team_ids: ['team_1']});
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
expect(wrapper.state('search')).toEqual(true);
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
expect(wrapper.state('searching')).toEqual(false);
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
@@ -284,12 +317,12 @@ describe('components/BrowseChannels', () => {
|
|||||||
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
||||||
|
|
||||||
jest.runOnlyPendingTimers();
|
jest.runOnlyPendingTimers();
|
||||||
expect(wrapper.instance().props.actions.searchMoreChannels).toHaveBeenCalledTimes(1);
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledTimes(1);
|
||||||
expect(wrapper.instance().props.actions.searchMoreChannels).toHaveBeenCalledWith('channel', false, false);
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledWith('channel', {include_deleted: true, nonAdminSearch: true, team_ids: ['team_1']});
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
expect(wrapper.state('search')).toEqual(true);
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
expect(wrapper.state('searching')).toEqual(false);
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
expect(wrapper.state('searchedChannels')).toEqual([searchResults.data[0]]);
|
expect(wrapper.state('searchedChannels')).toEqual([searchResults.data[0], searchResults.data[1], searchResults.data[2]]);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -300,7 +333,6 @@ describe('components/BrowseChannels', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
wrapper.instance().onChange = jest.fn();
|
wrapper.instance().onChange = jest.fn();
|
||||||
wrapper.instance().setState({shouldShowArchivedChannels: true});
|
|
||||||
wrapper.instance().search('channel');
|
wrapper.instance().search('channel');
|
||||||
expect(clearTimeout).toHaveBeenCalledTimes(1);
|
expect(clearTimeout).toHaveBeenCalledTimes(1);
|
||||||
expect(wrapper.instance().onChange).not.toHaveBeenCalled();
|
expect(wrapper.instance().onChange).not.toHaveBeenCalled();
|
||||||
@@ -309,10 +341,11 @@ describe('components/BrowseChannels', () => {
|
|||||||
expect(wrapper.instance().searchTimeoutId).not.toEqual('');
|
expect(wrapper.instance().searchTimeoutId).not.toEqual('');
|
||||||
expect(setTimeout).toHaveBeenCalledTimes(1);
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
||||||
|
wrapper.instance().changeFilter(Filter.Archived);
|
||||||
|
|
||||||
jest.runOnlyPendingTimers();
|
jest.runOnlyPendingTimers();
|
||||||
expect(wrapper.instance().props.actions.searchMoreChannels).toHaveBeenCalledTimes(1);
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledTimes(1);
|
||||||
expect(wrapper.instance().props.actions.searchMoreChannels).toHaveBeenCalledWith('channel', true, false);
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledWith('channel', {include_deleted: true, nonAdminSearch: true, team_ids: ['team_1']});
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
expect(wrapper.state('search')).toEqual(true);
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
expect(wrapper.state('searching')).toEqual(false);
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
@@ -320,4 +353,138 @@ describe('components/BrowseChannels', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should perform search on private channels and set the correct state', (done) => {
|
||||||
|
const wrapper = shallow<BrowseChannels>(
|
||||||
|
<BrowseChannels {...baseProps}/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.instance().onChange = jest.fn();
|
||||||
|
wrapper.instance().search('channel');
|
||||||
|
expect(clearTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().onChange).not.toHaveBeenCalled();
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(true);
|
||||||
|
expect(wrapper.instance().searchTimeoutId).not.toEqual('');
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
||||||
|
wrapper.instance().changeFilter(Filter.Private);
|
||||||
|
|
||||||
|
jest.runOnlyPendingTimers();
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledWith('channel', {include_deleted: true, nonAdminSearch: true, team_ids: ['team_1']});
|
||||||
|
process.nextTick(() => {
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
|
expect(wrapper.state('searchedChannels')).toEqual([searchResults.data[2]]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should perform search on public channels and set the correct state', (done) => {
|
||||||
|
const wrapper = shallow<BrowseChannels>(
|
||||||
|
<BrowseChannels {...baseProps}/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.instance().onChange = jest.fn();
|
||||||
|
wrapper.instance().search('channel');
|
||||||
|
expect(clearTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().onChange).not.toHaveBeenCalled();
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(true);
|
||||||
|
expect(wrapper.instance().searchTimeoutId).not.toEqual('');
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
||||||
|
wrapper.instance().changeFilter(Filter.Public);
|
||||||
|
|
||||||
|
jest.runOnlyPendingTimers();
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledWith('channel', {include_deleted: true, nonAdminSearch: true, team_ids: ['team_1']});
|
||||||
|
process.nextTick(() => {
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
|
expect(wrapper.state('searchedChannels')).toEqual([searchResults.data[0]]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should perform search on all channels and set the correct state when shouldHideJoinedChannels is true', (done) => {
|
||||||
|
const props = {
|
||||||
|
...baseProps,
|
||||||
|
shouldHideJoinedChannels: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow<BrowseChannels>(
|
||||||
|
<BrowseChannels {...props}/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.instance().onChange = jest.fn();
|
||||||
|
wrapper.instance().search('channel');
|
||||||
|
expect(clearTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().onChange).not.toHaveBeenCalled();
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(true);
|
||||||
|
expect(wrapper.instance().searchTimeoutId).not.toEqual('');
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
||||||
|
wrapper.instance().changeFilter(Filter.All);
|
||||||
|
|
||||||
|
jest.runOnlyPendingTimers();
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledWith('channel', {include_deleted: true, nonAdminSearch: true, team_ids: ['team_1']});
|
||||||
|
process.nextTick(() => {
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
|
expect(wrapper.state('searchedChannels')).toEqual([searchResults.data[0], searchResults.data[1]]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should perform search on all channels and set the correct state when shouldHideJoinedChannels is true and filter is private', (done) => {
|
||||||
|
const props = {
|
||||||
|
...baseProps,
|
||||||
|
shouldHideJoinedChannels: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow<BrowseChannels>(
|
||||||
|
<BrowseChannels {...props}/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.instance().onChange = jest.fn();
|
||||||
|
wrapper.instance().search('channel');
|
||||||
|
expect(clearTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().onChange).not.toHaveBeenCalled();
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(true);
|
||||||
|
expect(wrapper.instance().searchTimeoutId).not.toEqual('');
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
|
||||||
|
wrapper.instance().changeFilter(Filter.Private);
|
||||||
|
|
||||||
|
jest.runOnlyPendingTimers();
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledTimes(1);
|
||||||
|
expect(wrapper.instance().props.actions.searchAllChannels).toHaveBeenCalledWith('channel', {include_deleted: true, nonAdminSearch: true, team_ids: ['team_1']});
|
||||||
|
process.nextTick(() => {
|
||||||
|
expect(wrapper.state('search')).toEqual(true);
|
||||||
|
expect(wrapper.state('searching')).toEqual(false);
|
||||||
|
expect(wrapper.state('searchedChannels')).toEqual([]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should perform search on all channels and should not show private channels that user is not a member of', (done) => {
|
||||||
|
const wrapper = shallow<BrowseChannels>(
|
||||||
|
<BrowseChannels {...baseProps}/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.setState({search: true, searching: true});
|
||||||
|
wrapper.instance().onChange = jest.fn();
|
||||||
|
wrapper.instance().search('channel');
|
||||||
|
|
||||||
|
jest.runOnlyPendingTimers();
|
||||||
|
process.nextTick(() => {
|
||||||
|
expect(wrapper.state('searchedChannels')).toEqual([searchResults.data[0], searchResults.data[1], searchResults.data[2]]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,37 +4,46 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import Permissions from 'mattermost-redux/constants/permissions';
|
||||||
import {ActionResult} from 'mattermost-redux/types/actions';
|
import {ActionResult} from 'mattermost-redux/types/actions';
|
||||||
import {RelationOneToOne} from '@mattermost/types/utilities';
|
import {RelationOneToOne} from '@mattermost/types/utilities';
|
||||||
import {Channel, ChannelMembership} from '@mattermost/types/channels';
|
import {Channel, ChannelMembership, ChannelSearchOpts} from '@mattermost/types/channels';
|
||||||
import Permissions from 'mattermost-redux/constants/permissions';
|
import {GenericModal} from '@mattermost/components';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import NewChannelModal from 'components/new_channel_modal/new_channel_modal';
|
import NewChannelModal from 'components/new_channel_modal/new_channel_modal';
|
||||||
import SearchableChannelList from 'components/searchable_channel_list';
|
import SearchableChannelList from 'components/searchable_channel_list';
|
||||||
import TeamPermissionGate from 'components/permissions_gates/team_permission_gate';
|
import TeamPermissionGate from 'components/permissions_gates/team_permission_gate';
|
||||||
|
import LoadingScreen from 'components/loading_screen';
|
||||||
|
|
||||||
import {ModalData} from 'types/actions';
|
import {ModalData} from 'types/actions';
|
||||||
import {RhsState} from 'types/store/rhs';
|
import {RhsState} from 'types/store/rhs';
|
||||||
|
|
||||||
import {getHistory} from 'utils/browser_history';
|
import {getHistory} from 'utils/browser_history';
|
||||||
import {ModalIdentifiers, RHSStates, StoragePrefixes} from 'utils/constants';
|
import Constants, {ModalIdentifiers, RHSStates, StoragePrefixes} from 'utils/constants';
|
||||||
import {getRelativeChannelURL} from 'utils/url';
|
import {getRelativeChannelURL} from 'utils/url';
|
||||||
import {GenericModal} from '@mattermost/components';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import {localizeMessage} from 'utils/utils';
|
import {localizeMessage} from 'utils/utils';
|
||||||
import LoadingScreen from 'components/loading_screen';
|
|
||||||
|
|
||||||
import './browse_channels.scss';
|
import './browse_channels.scss';
|
||||||
|
|
||||||
const CHANNELS_CHUNK_SIZE = 50;
|
const CHANNELS_CHUNK_SIZE = 50;
|
||||||
const CHANNELS_PER_PAGE = 50;
|
const CHANNELS_PER_PAGE = 50;
|
||||||
const SEARCH_TIMEOUT_MILLISECONDS = 100;
|
const SEARCH_TIMEOUT_MILLISECONDS = 100;
|
||||||
|
export enum Filter {
|
||||||
|
All = 'All',
|
||||||
|
Public = 'Public',
|
||||||
|
Private = 'Private',
|
||||||
|
Archived = 'Archived',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterType = keyof typeof Filter;
|
||||||
|
|
||||||
type Actions = {
|
type Actions = {
|
||||||
getChannels: (teamId: string, page: number, perPage: number) => Promise<ActionResult<Channel[], Error>>;
|
getChannels: (teamId: string, page: number, perPage: number) => Promise<ActionResult<Channel[], Error>>;
|
||||||
getArchivedChannels: (teamId: string, page: number, channelsPerPage: number) => Promise<ActionResult<Channel[], Error>>;
|
getArchivedChannels: (teamId: string, page: number, channelsPerPage: number) => Promise<ActionResult<Channel[], Error>>;
|
||||||
joinChannel: (currentUserId: string, teamId: string, channelId: string) => Promise<ActionResult>;
|
joinChannel: (currentUserId: string, teamId: string, channelId: string) => Promise<ActionResult>;
|
||||||
searchMoreChannels: (term: string, shouldShowArchivedChannels: boolean, shouldHideJoinedChannels: boolean) => Promise<ActionResult>;
|
searchAllChannels: (term: string, opts?: ChannelSearchOpts) => Promise<ActionResult<Channel[], Error>>;
|
||||||
openModal: <P>(modalData: ModalData<P>) => void;
|
openModal: <P>(modalData: ModalData<P>) => void;
|
||||||
closeModal: (modalId: string) => void;
|
closeModal: (modalId: string) => void;
|
||||||
|
|
||||||
@@ -49,12 +58,12 @@ type Actions = {
|
|||||||
export type Props = {
|
export type Props = {
|
||||||
channels: Channel[];
|
channels: Channel[];
|
||||||
archivedChannels: Channel[];
|
archivedChannels: Channel[];
|
||||||
|
privateChannels: Channel[];
|
||||||
currentUserId: string;
|
currentUserId: string;
|
||||||
teamId: string;
|
teamId: string;
|
||||||
teamName: string;
|
teamName: string;
|
||||||
channelsRequestStarted?: boolean;
|
channelsRequestStarted?: boolean;
|
||||||
canShowArchivedChannels?: boolean;
|
canShowArchivedChannels?: boolean;
|
||||||
morePublicChannelsModalType?: string;
|
|
||||||
myChannelMemberships: RelationOneToOne<Channel, ChannelMembership>;
|
myChannelMemberships: RelationOneToOne<Channel, ChannelMembership>;
|
||||||
shouldHideJoinedChannels: boolean;
|
shouldHideJoinedChannels: boolean;
|
||||||
rhsState?: RhsState;
|
rhsState?: RhsState;
|
||||||
@@ -65,7 +74,7 @@ export type Props = {
|
|||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
shouldShowArchivedChannels: boolean;
|
filter: FilterType;
|
||||||
search: boolean;
|
search: boolean;
|
||||||
searchedChannels: Channel[];
|
searchedChannels: Channel[];
|
||||||
serverError: React.ReactNode | string;
|
serverError: React.ReactNode | string;
|
||||||
@@ -84,7 +93,7 @@ export default class BrowseChannels extends React.PureComponent<Props, State> {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
loading: true,
|
loading: true,
|
||||||
shouldShowArchivedChannels: this.props.morePublicChannelsModalType === 'private',
|
filter: Filter.All,
|
||||||
search: false,
|
search: false,
|
||||||
searchedChannels: [],
|
searchedChannels: [],
|
||||||
serverError: null,
|
serverError: null,
|
||||||
@@ -191,7 +200,7 @@ export default class BrowseChannels extends React.PureComponent<Props, State> {
|
|||||||
const searchTimeoutId = window.setTimeout(
|
const searchTimeoutId = window.setTimeout(
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
const {data} = await this.props.actions.searchMoreChannels(term, this.state.shouldShowArchivedChannels, this.props.shouldHideJoinedChannels);
|
const {data} = await this.props.actions.searchAllChannels(term, {team_ids: [this.props.teamId], nonAdminSearch: true, include_deleted: true});
|
||||||
if (searchTimeoutId !== this.searchTimeoutId) {
|
if (searchTimeoutId !== this.searchTimeoutId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -201,7 +210,7 @@ export default class BrowseChannels extends React.PureComponent<Props, State> {
|
|||||||
if (channelIDsForMemberCount.length > 0) {
|
if (channelIDsForMemberCount.length > 0) {
|
||||||
this.props.actions.getChannelsMemberCount(channelIDsForMemberCount);
|
this.props.actions.getChannelsMemberCount(channelIDsForMemberCount);
|
||||||
}
|
}
|
||||||
this.setSearchResults(data);
|
this.setSearchResults(data.filter((channel) => channel.team_id === this.props.teamId));
|
||||||
} else {
|
} else {
|
||||||
this.setState({searchedChannels: [], searching: false});
|
this.setState({searchedChannels: [], searching: false});
|
||||||
}
|
}
|
||||||
@@ -216,13 +225,27 @@ export default class BrowseChannels extends React.PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
setSearchResults = (channels: Channel[]) => {
|
setSearchResults = (channels: Channel[]) => {
|
||||||
this.setState({searchedChannels: this.state.shouldShowArchivedChannels ? channels.filter((c) => c.delete_at !== 0) : channels.filter((c) => c.delete_at === 0), searching: false});
|
// filter out private channels that the user is not a member of
|
||||||
|
let searchedChannels = channels.filter((c) => c.type !== Constants.PRIVATE_CHANNEL || this.isMemberOfChannel(c.id));
|
||||||
|
if (this.state.filter === Filter.Private) {
|
||||||
|
searchedChannels = channels.filter((c) => c.type === Constants.PRIVATE_CHANNEL && this.isMemberOfChannel(c.id));
|
||||||
|
}
|
||||||
|
if (this.state.filter === Filter.Public) {
|
||||||
|
searchedChannels = channels.filter((c) => c.type === Constants.OPEN_CHANNEL && c.delete_at === 0);
|
||||||
|
}
|
||||||
|
if (this.state.filter === Filter.Archived) {
|
||||||
|
searchedChannels = channels.filter((c) => c.delete_at !== 0);
|
||||||
|
}
|
||||||
|
if (this.props.shouldHideJoinedChannels) {
|
||||||
|
searchedChannels = this.getChannelsWithoutJoined(searchedChannels);
|
||||||
|
}
|
||||||
|
this.setState({searchedChannels, searching: false});
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleArchivedChannels = (shouldShowArchivedChannels: boolean) => {
|
changeFilter = (filter: FilterType) => {
|
||||||
// search again when switching channels to update search results
|
// search again when switching channels to update search results
|
||||||
this.search(this.state.searchTerm);
|
this.search(this.state.searchTerm);
|
||||||
this.setState({shouldShowArchivedChannels});
|
this.setState({filter});
|
||||||
};
|
};
|
||||||
|
|
||||||
isMemberOfChannel(channelId: string) {
|
isMemberOfChannel(channelId: string) {
|
||||||
@@ -235,36 +258,37 @@ export default class BrowseChannels extends React.PureComponent<Props, State> {
|
|||||||
this.props.actions.setGlobalItem(StoragePrefixes.HIDE_JOINED_CHANNELS, shouldHideJoinedChannels.toString());
|
this.props.actions.setGlobalItem(StoragePrefixes.HIDE_JOINED_CHANNELS, shouldHideJoinedChannels.toString());
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
getChannelsWithoutJoined = (channelList: Channel[]) => channelList.filter((channel) => !this.isMemberOfChannel(channel.id));
|
||||||
const {
|
|
||||||
channels,
|
|
||||||
archivedChannels,
|
|
||||||
teamId,
|
|
||||||
channelsRequestStarted,
|
|
||||||
shouldHideJoinedChannels,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const {
|
getActiveChannels = () => {
|
||||||
search,
|
const {channels, archivedChannels, shouldHideJoinedChannels, privateChannels} = this.props;
|
||||||
searchedChannels,
|
const {search, searchedChannels, filter} = this.state;
|
||||||
serverError: serverErrorState,
|
|
||||||
searching,
|
|
||||||
shouldShowArchivedChannels,
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
const otherChannelsWithoutJoined = channels.filter((channel) => !this.isMemberOfChannel(channel.id));
|
const allChannels = channels.concat(privateChannels).sort((a, b) => a.display_name.localeCompare(b.display_name));
|
||||||
const archivedChannelsWithoutJoined = archivedChannels.filter((channel) => !this.isMemberOfChannel(channel.id));
|
const allChannelsWithoutJoined = this.getChannelsWithoutJoined(allChannels);
|
||||||
|
const publicChannelsWithoutJoined = this.getChannelsWithoutJoined(channels);
|
||||||
|
const archivedChannelsWithoutJoined = this.getChannelsWithoutJoined(archivedChannels);
|
||||||
|
const privateChannelsWithoutJoined = this.getChannelsWithoutJoined(privateChannels);
|
||||||
|
|
||||||
if (shouldShowArchivedChannels && shouldHideJoinedChannels) {
|
const filterOptions = {
|
||||||
this.activeChannels = search ? searchedChannels : archivedChannelsWithoutJoined;
|
[Filter.All]: shouldHideJoinedChannels ? allChannelsWithoutJoined : allChannels,
|
||||||
} else if (shouldShowArchivedChannels && !shouldHideJoinedChannels) {
|
[Filter.Archived]: shouldHideJoinedChannels ? archivedChannelsWithoutJoined : archivedChannels,
|
||||||
this.activeChannels = search ? searchedChannels : archivedChannels;
|
[Filter.Private]: shouldHideJoinedChannels ? privateChannelsWithoutJoined : privateChannels,
|
||||||
} else if (!shouldShowArchivedChannels && shouldHideJoinedChannels) {
|
[Filter.Public]: shouldHideJoinedChannels ? publicChannelsWithoutJoined : channels,
|
||||||
this.activeChannels = search ? searchedChannels : otherChannelsWithoutJoined;
|
};
|
||||||
} else {
|
|
||||||
this.activeChannels = search ? searchedChannels : channels;
|
if (search) {
|
||||||
|
return searchedChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return filterOptions[filter] || filterOptions[Filter.All];
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {teamId, channelsRequestStarted, shouldHideJoinedChannels} = this.props;
|
||||||
|
const {search, serverError: serverErrorState, searching} = this.state;
|
||||||
|
this.activeChannels = this.getActiveChannels();
|
||||||
|
|
||||||
let serverError;
|
let serverError;
|
||||||
if (serverErrorState) {
|
if (serverErrorState) {
|
||||||
serverError =
|
serverError =
|
||||||
@@ -318,8 +342,8 @@ export default class BrowseChannels extends React.PureComponent<Props, State> {
|
|||||||
handleJoin={this.handleJoin}
|
handleJoin={this.handleJoin}
|
||||||
noResultsText={noResultsText}
|
noResultsText={noResultsText}
|
||||||
loading={search ? searching : channelsRequestStarted}
|
loading={search ? searching : channelsRequestStarted}
|
||||||
toggleArchivedChannels={this.toggleArchivedChannels}
|
changeFilter={this.changeFilter}
|
||||||
shouldShowArchivedChannels={this.state.shouldShowArchivedChannels}
|
filter={this.state.filter}
|
||||||
canShowArchivedChannels={this.props.canShowArchivedChannels}
|
canShowArchivedChannels={this.props.canShowArchivedChannels}
|
||||||
myChannelMemberships={this.props.myChannelMemberships}
|
myChannelMemberships={this.props.myChannelMemberships}
|
||||||
closeModal={this.props.actions.closeModal}
|
closeModal={this.props.actions.closeModal}
|
||||||
|
|||||||
@@ -6,15 +6,14 @@ import {ActionCreatorsMapObject, bindActionCreators, Dispatch} from 'redux';
|
|||||||
|
|
||||||
import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
||||||
import {RequestStatus} from 'mattermost-redux/constants';
|
import {RequestStatus} from 'mattermost-redux/constants';
|
||||||
import {Channel} from '@mattermost/types/channels';
|
import {Channel, ChannelSearchOpts} from '@mattermost/types/channels';
|
||||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||||
import {Action, ActionResult} from 'mattermost-redux/types/actions';
|
import {Action, ActionResult} from 'mattermost-redux/types/actions';
|
||||||
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
|
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
|
||||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||||
import {getChannels, getArchivedChannels, joinChannel, getChannelsMemberCount} from 'mattermost-redux/actions/channels';
|
import {getChannels, getArchivedChannels, joinChannel, getChannelsMemberCount, searchAllChannels} from 'mattermost-redux/actions/channels';
|
||||||
import {getChannelsInCurrentTeam, getMyChannelMemberships, getChannelsMemberCount as getChannelsMemberCountSelector} from 'mattermost-redux/selectors/entities/channels';
|
import {getChannelsInCurrentTeam, getMyChannelMemberships, getChannelsMemberCount as getChannelsMemberCountSelector} from 'mattermost-redux/selectors/entities/channels';
|
||||||
|
|
||||||
import {searchMoreChannels} from 'actions/channel_actions';
|
|
||||||
import {openModal, closeModal} from 'actions/views/modals';
|
import {openModal, closeModal} from 'actions/views/modals';
|
||||||
import {closeRightHandSide} from 'actions/views/rhs';
|
import {closeRightHandSide} from 'actions/views/rhs';
|
||||||
|
|
||||||
@@ -40,6 +39,12 @@ const getArchivedOtherChannels = createSelector(
|
|||||||
(channels: Channel[]) => channels && channels.filter((c) => c.delete_at !== 0),
|
(channels: Channel[]) => channels && channels.filter((c) => c.delete_at !== 0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getPrivateChannelsSelector = createSelector(
|
||||||
|
'getPrivateChannelsSelector',
|
||||||
|
getChannelsInCurrentTeam,
|
||||||
|
(channels: Channel[]) => channels && channels.filter((c) => c.type === Constants.PRIVATE_CHANNEL),
|
||||||
|
);
|
||||||
|
|
||||||
function mapStateToProps(state: GlobalState) {
|
function mapStateToProps(state: GlobalState) {
|
||||||
const team = getCurrentTeam(state) || {};
|
const team = getCurrentTeam(state) || {};
|
||||||
const getGlobalItem = makeGetGlobalItem(StoragePrefixes.HIDE_JOINED_CHANNELS, 'false');
|
const getGlobalItem = makeGetGlobalItem(StoragePrefixes.HIDE_JOINED_CHANNELS, 'false');
|
||||||
@@ -47,6 +52,7 @@ function mapStateToProps(state: GlobalState) {
|
|||||||
return {
|
return {
|
||||||
channels: getChannelsWithoutArchived(state) || [],
|
channels: getChannelsWithoutArchived(state) || [],
|
||||||
archivedChannels: getArchivedOtherChannels(state) || [],
|
archivedChannels: getArchivedOtherChannels(state) || [],
|
||||||
|
privateChannels: getPrivateChannelsSelector(state) || [],
|
||||||
currentUserId: getCurrentUserId(state),
|
currentUserId: getCurrentUserId(state),
|
||||||
teamId: team.id,
|
teamId: team.id,
|
||||||
teamName: team.name,
|
teamName: team.name,
|
||||||
@@ -63,8 +69,9 @@ function mapStateToProps(state: GlobalState) {
|
|||||||
type Actions = {
|
type Actions = {
|
||||||
getChannels: (teamId: string, page: number, perPage: number) => Promise<ActionResult<Channel[], Error>>;
|
getChannels: (teamId: string, page: number, perPage: number) => Promise<ActionResult<Channel[], Error>>;
|
||||||
getArchivedChannels: (teamId: string, page: number, channelsPerPage: number) => Promise<ActionResult<Channel[], Error>>;
|
getArchivedChannels: (teamId: string, page: number, channelsPerPage: number) => Promise<ActionResult<Channel[], Error>>;
|
||||||
|
getPrivateChannels: (teamId: string, page: number, channelsPerPage: number) => Promise<ActionResult<Channel[], Error>>;
|
||||||
joinChannel: (currentUserId: string, teamId: string, channelId: string) => Promise<ActionResult>;
|
joinChannel: (currentUserId: string, teamId: string, channelId: string) => Promise<ActionResult>;
|
||||||
searchMoreChannels: (term: string, shouldShowArchivedChannels: boolean) => Promise<ActionResult>;
|
searchAllChannels: (term: string, opts?: ChannelSearchOpts) => Promise<ActionResult<Channel[], Error>>;
|
||||||
openModal: <P>(modalData: ModalData<P>) => void;
|
openModal: <P>(modalData: ModalData<P>) => void;
|
||||||
closeModal: (modalId: string) => void;
|
closeModal: (modalId: string) => void;
|
||||||
setGlobalItem: (name: string, value: string) => void;
|
setGlobalItem: (name: string, value: string) => void;
|
||||||
@@ -78,7 +85,7 @@ function mapDispatchToProps(dispatch: Dispatch) {
|
|||||||
getChannels,
|
getChannels,
|
||||||
getArchivedChannels,
|
getArchivedChannels,
|
||||||
joinChannel,
|
joinChannel,
|
||||||
searchMoreChannels,
|
searchAllChannels,
|
||||||
openModal,
|
openModal,
|
||||||
closeModal,
|
closeModal,
|
||||||
setGlobalItem,
|
setGlobalItem,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import React from 'react';
|
|||||||
import {shallow} from 'enzyme';
|
import {shallow} from 'enzyme';
|
||||||
|
|
||||||
import SearchableChannelList from 'components/searchable_channel_list';
|
import SearchableChannelList from 'components/searchable_channel_list';
|
||||||
|
import {Filter} from './browse_channels/browse_channels';
|
||||||
|
|
||||||
describe('components/SearchableChannelList', () => {
|
describe('components/SearchableChannelList', () => {
|
||||||
const baseProps = {
|
const baseProps = {
|
||||||
@@ -18,11 +19,12 @@ describe('components/SearchableChannelList', () => {
|
|||||||
toggleArchivedChannels: jest.fn(),
|
toggleArchivedChannels: jest.fn(),
|
||||||
closeModal: jest.fn(),
|
closeModal: jest.fn(),
|
||||||
hideJoinedChannelsPreference: jest.fn(),
|
hideJoinedChannelsPreference: jest.fn(),
|
||||||
|
changeFilter: jest.fn(),
|
||||||
myChannelMemberships: {},
|
myChannelMemberships: {},
|
||||||
shouldShowArchivedChannels: false,
|
|
||||||
canShowArchivedChannels: false,
|
canShowArchivedChannels: false,
|
||||||
rememberHideJoinedChannelsChecked: false,
|
rememberHideJoinedChannelsChecked: false,
|
||||||
noResultsText: <>{'no channel found'}</>,
|
noResultsText: <>{'no channel found'}</>,
|
||||||
|
filter: Filter.All,
|
||||||
};
|
};
|
||||||
|
|
||||||
test('should match init snapshot', () => {
|
test('should match init snapshot', () => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
import {ArchiveOutlineIcon, CheckIcon, ChevronDownIcon, GlobeIcon, LockOutlineIcon, MagnifyIcon, AccountOutlineIcon} from '@mattermost/compass-icons/components';
|
import {ArchiveOutlineIcon, CheckIcon, ChevronDownIcon, GlobeIcon, LockOutlineIcon, MagnifyIcon, AccountOutlineIcon, GlobeCheckedIcon} from '@mattermost/compass-icons/components';
|
||||||
import {Channel, ChannelMembership} from '@mattermost/types/channels';
|
import {Channel, ChannelMembership} from '@mattermost/types/channels';
|
||||||
import {RelationOneToOne} from '@mattermost/types/utilities';
|
import {RelationOneToOne} from '@mattermost/types/utilities';
|
||||||
import {isPrivateChannel} from 'mattermost-redux/utils/channel_utils';
|
import {isPrivateChannel} from 'mattermost-redux/utils/channel_utils';
|
||||||
@@ -17,6 +17,7 @@ import QuickInput from 'components/quick_input';
|
|||||||
import CheckboxCheckedIcon from 'components/widgets/icons/checkbox_checked_icon';
|
import CheckboxCheckedIcon from 'components/widgets/icons/checkbox_checked_icon';
|
||||||
import LocalizedInput from 'components/localized_input/localized_input';
|
import LocalizedInput from 'components/localized_input/localized_input';
|
||||||
import MagnifyingGlassSVG from 'components/common/svg_images_components/magnifying_glass_svg';
|
import MagnifyingGlassSVG from 'components/common/svg_images_components/magnifying_glass_svg';
|
||||||
|
import * as Menu from 'components/menu';
|
||||||
|
|
||||||
import * as UserAgent from 'utils/user_agent';
|
import * as UserAgent from 'utils/user_agent';
|
||||||
import Constants, {ModalIdentifiers} from 'utils/constants';
|
import Constants, {ModalIdentifiers} from 'utils/constants';
|
||||||
@@ -24,9 +25,8 @@ import {localizeMessage, localizeAndFormatMessage} from 'utils/utils';
|
|||||||
import {isArchivedChannel} from 'utils/channel_utils';
|
import {isArchivedChannel} from 'utils/channel_utils';
|
||||||
|
|
||||||
import {t} from 'utils/i18n';
|
import {t} from 'utils/i18n';
|
||||||
import MenuWrapper from './widgets/menu/menu_wrapper';
|
|
||||||
import Menu from './widgets/menu/menu';
|
|
||||||
import {isKeyPressed} from 'utils/keyboard';
|
import {isKeyPressed} from 'utils/keyboard';
|
||||||
|
import {Filter, FilterType} from './browse_channels/browse_channels';
|
||||||
|
|
||||||
const NEXT_BUTTON_TIMEOUT_MILLISECONDS = 500;
|
const NEXT_BUTTON_TIMEOUT_MILLISECONDS = 500;
|
||||||
|
|
||||||
@@ -38,8 +38,8 @@ type Props = {
|
|||||||
search: (term: string) => void;
|
search: (term: string) => void;
|
||||||
handleJoin: (channel: Channel, done: () => void) => void;
|
handleJoin: (channel: Channel, done: () => void) => void;
|
||||||
noResultsText: JSX.Element;
|
noResultsText: JSX.Element;
|
||||||
toggleArchivedChannels: (shouldShowArchivedChannels: boolean) => void;
|
changeFilter: (filter: FilterType) => void;
|
||||||
shouldShowArchivedChannels: boolean;
|
filter: FilterType;
|
||||||
myChannelMemberships: RelationOneToOne<Channel, ChannelMembership>;
|
myChannelMemberships: RelationOneToOne<Channel, ChannelMembership>;
|
||||||
closeModal: (modalId: string) => void;
|
closeModal: (modalId: string) => void;
|
||||||
hideJoinedChannelsPreference: (shouldHideJoinedChannels: boolean) => void;
|
hideJoinedChannelsPreference: (shouldHideJoinedChannels: boolean) => void;
|
||||||
@@ -250,12 +250,6 @@ export default class SearchableChannelList extends React.PureComponent<Props, St
|
|||||||
handleClear = () => {
|
handleClear = () => {
|
||||||
this.setState({channelSearchValue: ''}, () => this.doSearch());
|
this.setState({channelSearchValue: ''}, () => this.doSearch());
|
||||||
};
|
};
|
||||||
toggleArchivedChannelsOn = () => {
|
|
||||||
this.props.toggleArchivedChannels(true);
|
|
||||||
};
|
|
||||||
toggleArchivedChannelsOff = () => {
|
|
||||||
this.props.toggleArchivedChannels(false);
|
|
||||||
};
|
|
||||||
handleChecked = () => {
|
handleChecked = () => {
|
||||||
// If it was checked, and now we're unchecking it, clear the preference
|
// If it was checked, and now we're unchecking it, clear the preference
|
||||||
if (this.props.rememberHideJoinedChannelsChecked) {
|
if (this.props.rememberHideJoinedChannelsChecked) {
|
||||||
@@ -264,6 +258,84 @@ export default class SearchableChannelList extends React.PureComponent<Props, St
|
|||||||
this.props.hideJoinedChannelsPreference(true);
|
this.props.hideJoinedChannelsPreference(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
getEmptyStateMessage = () => {
|
||||||
|
if (this.state.channelSearchValue.length > 0) {
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='more_channels.noMore'
|
||||||
|
tagName='strong'
|
||||||
|
defaultMessage='No results for {text}'
|
||||||
|
values={{text: this.state.channelSearchValue}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
switch (this.props.filter) {
|
||||||
|
case Filter.Archived:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id={'more_channels.noArchived'}
|
||||||
|
tagName='strong'
|
||||||
|
defaultMessage={'No archived channels'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case Filter.Private:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id={'more_channels.noPrivate'}
|
||||||
|
tagName='strong'
|
||||||
|
defaultMessage={'No private channels'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case Filter.Public:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id={'more_channels.noPublic'}
|
||||||
|
tagName='strong'
|
||||||
|
defaultMessage={'No public channels'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id={'more_channels.noChannels'}
|
||||||
|
tagName='strong'
|
||||||
|
defaultMessage={'No channels'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getFilterLabel = () => {
|
||||||
|
switch (this.props.filter) {
|
||||||
|
case Filter.Archived:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='more_channels.show_archived_channels'
|
||||||
|
defaultMessage='Channel Type: Archived'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case Filter.Public:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='more_channels.show_public_channels'
|
||||||
|
defaultMessage='Channel Type: Public'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case Filter.Private:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='more_channels.show_private_channels'
|
||||||
|
defaultMessage='Channel Type: Private'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='more_channels.show_all_channels'
|
||||||
|
defaultMessage='Channel Type: All'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const channels = this.props.channels;
|
const channels = this.props.channels;
|
||||||
@@ -271,27 +343,6 @@ export default class SearchableChannelList extends React.PureComponent<Props, St
|
|||||||
let nextButton;
|
let nextButton;
|
||||||
let previousButton;
|
let previousButton;
|
||||||
|
|
||||||
let emptyStateMessage = (
|
|
||||||
<FormattedMessage
|
|
||||||
id={this.props.shouldShowArchivedChannels ? t('more_channels.noArchived') : t('more_channels.noPublic')}
|
|
||||||
tagName='strong'
|
|
||||||
defaultMessage={this.props.shouldShowArchivedChannels ? 'No archived channels' : 'No public channels'}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.state.channelSearchValue.length > 0) {
|
|
||||||
emptyStateMessage = (
|
|
||||||
<FormattedMessage
|
|
||||||
id='more_channels.noMore'
|
|
||||||
tagName='strong'
|
|
||||||
defaultMessage='No results for {text}'
|
|
||||||
values={{
|
|
||||||
text: this.state.channelSearchValue,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.loading && channels.length === 0) {
|
if (this.props.loading && channels.length === 0) {
|
||||||
listContent = <LoadingScreen/>;
|
listContent = <LoadingScreen/>;
|
||||||
} else if (channels.length === 0) {
|
} else if (channels.length === 0) {
|
||||||
@@ -305,7 +356,7 @@ export default class SearchableChannelList extends React.PureComponent<Props, St
|
|||||||
>
|
>
|
||||||
<MagnifyingGlassSVG/>
|
<MagnifyingGlassSVG/>
|
||||||
<h3 className='primary-message'>
|
<h3 className='primary-message'>
|
||||||
{emptyStateMessage}
|
{this.getEmptyStateMessage()}
|
||||||
</h3>
|
</h3>
|
||||||
{this.props.noResultsText}
|
{this.props.noResultsText}
|
||||||
</div>
|
</div>
|
||||||
@@ -371,51 +422,98 @@ export default class SearchableChannelList extends React.PureComponent<Props, St
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
let channelDropdown;
|
const checkIcon = (
|
||||||
let checkIcon;
|
<CheckIcon
|
||||||
|
size={18}
|
||||||
|
color={'var(--button-bg)'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const channelDropdownItems = [
|
||||||
|
<Menu.Item
|
||||||
|
key='channelsMoreDropdownAll'
|
||||||
|
id='channelsMoreDropdownAll'
|
||||||
|
onClick={() => this.props.changeFilter(Filter.All)}
|
||||||
|
leadingElement={<GlobeCheckedIcon size={16}/>}
|
||||||
|
labels={
|
||||||
|
<FormattedMessage
|
||||||
|
id='suggestion.all'
|
||||||
|
defaultMessage='All channel types'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
trailingElements={this.props.filter === Filter.All ? checkIcon : null}
|
||||||
|
aria-label={localizeMessage('suggestion.all', 'All channel types')}
|
||||||
|
/>,
|
||||||
|
<Menu.Item
|
||||||
|
key='channelsMoreDropdownPublic'
|
||||||
|
id='channelsMoreDropdownPublic'
|
||||||
|
onClick={() => this.props.changeFilter(Filter.Public)}
|
||||||
|
leadingElement={<GlobeIcon size={16}/>}
|
||||||
|
labels={
|
||||||
|
<FormattedMessage
|
||||||
|
id='suggestion.public'
|
||||||
|
defaultMessage='Public channels'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
trailingElements={this.props.filter === Filter.Public ? checkIcon : null}
|
||||||
|
aria-label={localizeMessage('suggestion.public', 'Public channels')}
|
||||||
|
/>,
|
||||||
|
<Menu.Item
|
||||||
|
key='channelsMoreDropdownPrivate'
|
||||||
|
id='channelsMoreDropdownPrivate'
|
||||||
|
onClick={() => this.props.changeFilter(Filter.Private)}
|
||||||
|
leadingElement={<LockOutlineIcon size={16}/>}
|
||||||
|
labels={
|
||||||
|
<FormattedMessage
|
||||||
|
id='suggestion.private'
|
||||||
|
defaultMessage='Private channels'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
trailingElements={this.props.filter === Filter.Private ? checkIcon : null}
|
||||||
|
aria-label={localizeMessage('suggestion.private', 'Private channels')}
|
||||||
|
/>,
|
||||||
|
];
|
||||||
|
|
||||||
if (this.props.canShowArchivedChannels) {
|
if (this.props.canShowArchivedChannels) {
|
||||||
checkIcon = (
|
channelDropdownItems.push(
|
||||||
<CheckIcon
|
<Menu.Separator/>,
|
||||||
size={18}
|
<Menu.Item
|
||||||
color={'var(--button-bg)'}
|
id='channelsMoreDropdownArchived'
|
||||||
/>
|
onClick={() => this.props.changeFilter(Filter.Archived)}
|
||||||
);
|
leadingElement={<ArchiveOutlineIcon size={16}/>}
|
||||||
channelDropdown = (
|
labels={
|
||||||
<MenuWrapper id='channelsMoreDropdown'>
|
<FormattedMessage
|
||||||
<button id='menuWrapper'>
|
id='suggestion.archive'
|
||||||
<span>{this.props.shouldShowArchivedChannels ? localizeMessage('more_channels.show_archived_channels', 'Channel Type: Archived') : localizeMessage('more_channels.show_public_channels', 'Channel Type: Public')}</span>
|
defaultMessage='Archived channels'
|
||||||
<ChevronDownIcon
|
|
||||||
color={'rgba(var(--center-channel-color-rgb), 0.64)'}
|
|
||||||
size={16}
|
|
||||||
/>
|
/>
|
||||||
</button>
|
}
|
||||||
<Menu
|
trailingElements={this.props.filter === Filter.Archived ? checkIcon : null}
|
||||||
openLeft={false}
|
aria-label={localizeMessage('suggestion.archive', 'Archived channels')}
|
||||||
ariaLabel={localizeMessage('more_channels.title', 'Browse channels')}
|
/>,
|
||||||
>
|
|
||||||
<div id='modalPreferenceContainer'>
|
|
||||||
<Menu.ItemAction
|
|
||||||
id='channelsMoreDropdownPublic'
|
|
||||||
onClick={this.toggleArchivedChannelsOff}
|
|
||||||
icon={<GlobeIcon size={16}/>}
|
|
||||||
text={localizeMessage('suggestion.search.public', 'Public Channels')}
|
|
||||||
rightDecorator={this.props.shouldShowArchivedChannels ? null : checkIcon}
|
|
||||||
ariaLabel={localizeMessage('suggestion.search.public', 'Public Channels')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Menu.ItemAction
|
|
||||||
id='channelsMoreDropdownArchived'
|
|
||||||
onClick={this.toggleArchivedChannelsOn}
|
|
||||||
icon={<ArchiveOutlineIcon size={16}/>}
|
|
||||||
text={localizeMessage('suggestion.archive', 'Archived Channels')}
|
|
||||||
rightDecorator={this.props.shouldShowArchivedChannels ? checkIcon : null}
|
|
||||||
ariaLabel={localizeMessage('suggestion.archive', 'Archived Channels')}
|
|
||||||
/>
|
|
||||||
</Menu>
|
|
||||||
</MenuWrapper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const menuButton = (
|
||||||
|
<>
|
||||||
|
{this.getFilterLabel()}
|
||||||
|
<ChevronDownIcon
|
||||||
|
color={'rgba(var(--center-channel-color-rgb), 0.64)'}
|
||||||
|
size={16}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
const channelDropdown = (
|
||||||
|
<Menu.Container
|
||||||
|
menuButton={{
|
||||||
|
id: 'menuWrapper',
|
||||||
|
children: menuButton,
|
||||||
|
}}
|
||||||
|
menu={{
|
||||||
|
id: 'browseChannelsDropdown',
|
||||||
|
'aria-label': localizeMessage('more_channels.title', 'Browse channels'),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{channelDropdownItems.map((item) => item)}
|
||||||
|
</Menu.Container >
|
||||||
|
);
|
||||||
|
|
||||||
const hideJoinedButtonClass = classNames('get-app__checkbox', {checked: this.props.rememberHideJoinedChannelsChecked});
|
const hideJoinedButtonClass = classNames('get-app__checkbox', {checked: this.props.rememberHideJoinedChannelsChecked});
|
||||||
const hideJoinedPreferenceCheckbox = (
|
const hideJoinedPreferenceCheckbox = (
|
||||||
@@ -425,8 +523,7 @@ export default class SearchableChannelList extends React.PureComponent<Props, St
|
|||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className={hideJoinedButtonClass}
|
className={hideJoinedButtonClass}
|
||||||
aria-label={this.props.rememberHideJoinedChannelsChecked ? localizeMessage('more_channels.hide_joined_checked', 'Hide joined channels checkbox, checked') : localizeMessage('more_channels.hide_joined_not_checked', 'Hide joined channels checkbox, not checked')
|
aria-label={this.props.rememberHideJoinedChannelsChecked ? localizeMessage('more_channels.hide_joined_checked', 'Hide joined channels checkbox, checked') : localizeMessage('more_channels.hide_joined_not_checked', 'Hide joined channels checkbox, not checked')}
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{this.props.rememberHideJoinedChannelsChecked ? <CheckboxCheckedIcon/> : null}
|
{this.props.rememberHideJoinedChannelsChecked ? <CheckboxCheckedIcon/> : null}
|
||||||
</button>
|
</button>
|
||||||
@@ -483,8 +580,3 @@ export default class SearchableChannelList extends React.PureComponent<Props, St
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchableChannelList.defaultProps = {
|
|
||||||
// channels: [],
|
|
||||||
// isSearch: false,
|
|
||||||
// };
|
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const AddChannelsCtaButton = (): JSX.Element | null => {
|
|||||||
dispatch(openModal({
|
dispatch(openModal({
|
||||||
modalId: ModalIdentifiers.MORE_CHANNELS,
|
modalId: ModalIdentifiers.MORE_CHANNELS,
|
||||||
dialogType: BrowseChannels,
|
dialogType: BrowseChannels,
|
||||||
dialogProps: {morePublicChannelsModalType: 'public'},
|
|
||||||
}));
|
}));
|
||||||
trackEvent('ui', 'browse_channels_button_is_clicked');
|
trackEvent('ui', 'browse_channels_button_is_clicked');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -150,7 +150,6 @@ export default class Sidebar extends React.PureComponent<Props, State> {
|
|||||||
this.props.actions.openModal({
|
this.props.actions.openModal({
|
||||||
modalId: ModalIdentifiers.MORE_CHANNELS,
|
modalId: ModalIdentifiers.MORE_CHANNELS,
|
||||||
dialogType: BrowseChannels,
|
dialogType: BrowseChannels,
|
||||||
dialogProps: {morePublicChannelsModalType: 'public'},
|
|
||||||
});
|
});
|
||||||
trackEvent('ui', 'ui_channels_more_public_v2');
|
trackEvent('ui', 'ui_channels_more_public_v2');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -205,10 +205,10 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
<CloseIcon>
|
<CloseIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -300,10 +300,10 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
<MagnifyIcon>
|
<MagnifyIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -1263,10 +1263,10 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -1482,10 +1482,10 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -1701,10 +1701,10 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -1920,10 +1920,10 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -2139,10 +2139,10 @@ exports[`component/user_group_popover should match snapshot 1`] = `
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
|
|||||||
@@ -533,10 +533,10 @@ exports[`component/user_group_popover/group_member_list should match snapshot 1`
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -752,10 +752,10 @@ exports[`component/user_group_popover/group_member_list should match snapshot 1`
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -971,10 +971,10 @@ exports[`component/user_group_popover/group_member_list should match snapshot 1`
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -1190,10 +1190,10 @@ exports[`component/user_group_popover/group_member_list should match snapshot 1`
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -1409,10 +1409,10 @@ exports[`component/user_group_popover/group_member_list should match snapshot 1`
|
|||||||
<SendIcon>
|
<SendIcon>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height={24}
|
height="1em"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={24}
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
|
|||||||
@@ -4021,11 +4021,15 @@
|
|||||||
"more_channels.membership_indicator": "Membership Indicator: Joined",
|
"more_channels.membership_indicator": "Membership Indicator: Joined",
|
||||||
"more_channels.next": "Next",
|
"more_channels.next": "Next",
|
||||||
"more_channels.noArchived": "No archived channels",
|
"more_channels.noArchived": "No archived channels",
|
||||||
|
"more_channels.noChannels": "No channels",
|
||||||
"more_channels.noMore": "No results for \"{text}\"",
|
"more_channels.noMore": "No results for \"{text}\"",
|
||||||
|
"more_channels.noPrivate": "No private channels",
|
||||||
"more_channels.noPublic": "No public channels",
|
"more_channels.noPublic": "No public channels",
|
||||||
"more_channels.prev": "Previous",
|
"more_channels.prev": "Previous",
|
||||||
"more_channels.searchError": "Try searching different keywords, checking for typos or adjusting the filters.",
|
"more_channels.searchError": "Try searching different keywords, checking for typos or adjusting the filters.",
|
||||||
|
"more_channels.show_all_channels": "Channel Type: All",
|
||||||
"more_channels.show_archived_channels": "Channel Type: Archived",
|
"more_channels.show_archived_channels": "Channel Type: Archived",
|
||||||
|
"more_channels.show_private_channels": "Channel Type: Private",
|
||||||
"more_channels.show_public_channels": "Channel Type: Public",
|
"more_channels.show_public_channels": "Channel Type: Public",
|
||||||
"more_channels.title": "Browse Channels",
|
"more_channels.title": "Browse Channels",
|
||||||
"more_channels.view": "View",
|
"more_channels.view": "View",
|
||||||
@@ -4936,7 +4940,8 @@
|
|||||||
"success_modal.return_to_workspace": "Return to workspace",
|
"success_modal.return_to_workspace": "Return to workspace",
|
||||||
"success_modal.subtitle": "Your final bill will be prorated. Your workspace now has {plan} limits.",
|
"success_modal.subtitle": "Your final bill will be prorated. Your workspace now has {plan} limits.",
|
||||||
"suggestion_list.no_matches": "No items match __{value}__",
|
"suggestion_list.no_matches": "No items match __{value}__",
|
||||||
"suggestion.archive": "Archived Channels",
|
"suggestion.all": "All channel types",
|
||||||
|
"suggestion.archive": "Archived channels",
|
||||||
"suggestion.commands": "Commands",
|
"suggestion.commands": "Commands",
|
||||||
"suggestion.emoji": "Emoji",
|
"suggestion.emoji": "Emoji",
|
||||||
"suggestion.group.members": "{member_count} {member_count, plural, one {member} other {members}}",
|
"suggestion.group.members": "{member_count} {member_count, plural, one {member} other {members}}",
|
||||||
@@ -4954,6 +4959,8 @@
|
|||||||
"suggestion.mention.special": "Special Mentions",
|
"suggestion.mention.special": "Special Mentions",
|
||||||
"suggestion.mention.unread": "Unread",
|
"suggestion.mention.unread": "Unread",
|
||||||
"suggestion.mention.unread.channels": "Unread Channels",
|
"suggestion.mention.unread.channels": "Unread Channels",
|
||||||
|
"suggestion.private": "Private channels",
|
||||||
|
"suggestion.public": "Public channels",
|
||||||
"suggestion.search.direct": "Direct Messages",
|
"suggestion.search.direct": "Direct Messages",
|
||||||
"suggestion.search.group": "Group Mentions",
|
"suggestion.search.group": "Group Mentions",
|
||||||
"suggestion.search.private": "Private Channels",
|
"suggestion.search.private": "Private Channels",
|
||||||
|
|||||||
14
webapp/package-lock.json
сгенерированный
14
webapp/package-lock.json
сгенерированный
@@ -59,7 +59,7 @@
|
|||||||
"@guyplusplus/turndown-plugin-gfm": "1.0.7",
|
"@guyplusplus/turndown-plugin-gfm": "1.0.7",
|
||||||
"@mattermost/client": "*",
|
"@mattermost/client": "*",
|
||||||
"@mattermost/compass-components": "^0.2.12",
|
"@mattermost/compass-components": "^0.2.12",
|
||||||
"@mattermost/compass-icons": "0.1.34",
|
"@mattermost/compass-icons": "0.1.37",
|
||||||
"@mattermost/types": "*",
|
"@mattermost/types": "*",
|
||||||
"@mui/base": "5.0.0-alpha.127",
|
"@mui/base": "5.0.0-alpha.127",
|
||||||
"@mui/material": "5.11.16",
|
"@mui/material": "5.11.16",
|
||||||
@@ -229,6 +229,11 @@
|
|||||||
"yup": "0.32.11"
|
"yup": "0.32.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"channels/node_modules/@mattermost/compass-icons": {
|
||||||
|
"version": "0.1.37",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mattermost/compass-icons/-/compass-icons-0.1.37.tgz",
|
||||||
|
"integrity": "sha512-4me1W0hj1nu8A1gpdQA6cij/hyb2P7uIYMJQ+xrNvn5ImTRfQ67LEdyNOa/LY+oT1NO2ui6kKOs8oLUehIaneg=="
|
||||||
|
},
|
||||||
"channels/node_modules/@mui/base": {
|
"channels/node_modules/@mui/base": {
|
||||||
"version": "5.0.0-alpha.127",
|
"version": "5.0.0-alpha.127",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.127.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.127.tgz",
|
||||||
@@ -35641,7 +35646,7 @@
|
|||||||
"@hot-loader/react-dom": "17.0.2",
|
"@hot-loader/react-dom": "17.0.2",
|
||||||
"@mattermost/client": "*",
|
"@mattermost/client": "*",
|
||||||
"@mattermost/compass-components": "^0.2.12",
|
"@mattermost/compass-components": "^0.2.12",
|
||||||
"@mattermost/compass-icons": "0.1.34",
|
"@mattermost/compass-icons": "0.1.37",
|
||||||
"@mattermost/types": "*",
|
"@mattermost/types": "*",
|
||||||
"@mui/base": "5.0.0-alpha.127",
|
"@mui/base": "5.0.0-alpha.127",
|
||||||
"@mui/material": "5.11.16",
|
"@mui/material": "5.11.16",
|
||||||
@@ -35807,6 +35812,11 @@
|
|||||||
"zen-observable": "0.9.0"
|
"zen-observable": "0.9.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mattermost/compass-icons": {
|
||||||
|
"version": "0.1.37",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mattermost/compass-icons/-/compass-icons-0.1.37.tgz",
|
||||||
|
"integrity": "sha512-4me1W0hj1nu8A1gpdQA6cij/hyb2P7uIYMJQ+xrNvn5ImTRfQ67LEdyNOa/LY+oT1NO2ui6kKOs8oLUehIaneg=="
|
||||||
|
},
|
||||||
"@mui/base": {
|
"@mui/base": {
|
||||||
"version": "5.0.0-alpha.127",
|
"version": "5.0.0-alpha.127",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.127.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.127.tgz",
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user