From d0a67cd84ad03d9c49ed9378408d32494843a054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Espino=20Garc=C3=ADa?= Date: Mon, 22 Apr 2024 12:42:13 +0200 Subject: [PATCH] Fix types so the store can return undefined teams (#26386) * Fix types so the store can return undefined teams * Fix post test * fix snapshots * Address feedback --- webapp/channels/src/actions/views/channel.ts | 7 ++- .../src/actions/views/onboarding_tasks.ts | 4 ++ .../add_groups_to_team_modal.tsx | 4 +- .../add_groups_to_team_modal/index.ts | 10 ++--- .../channel_details.test.tsx.snap | 45 +++++++++++++++++-- .../channel/details/channel_details.test.tsx | 21 ++++----- .../channel/details/channel_details.tsx | 4 +- .../channel/details/channel_profile.test.tsx | 7 +-- .../channel/details/channel_profile.tsx | 4 +- .../channel/details/index.ts | 4 +- .../team/details/team_details.tsx | 39 +++++++++------- .../team/details/team_members/index.ts | 2 +- .../details/team_members/team_members.tsx | 2 +- .../backstage/backstage_controller.tsx | 2 +- .../src/components/backstage/index.ts | 2 +- .../browse_channels/browse_channels.tsx | 10 ++++- .../src/components/browse_channels/index.ts | 8 ++-- .../close_message/close_message.tsx | 6 ++- .../src/components/channel_info_rhs/index.ts | 4 +- .../channel_invite_modal.tsx | 2 +- .../components/channel_invite_modal/index.ts | 6 +-- .../team_warning_banner.tsx | 8 ++-- .../components/channel_members_rhs/index.ts | 2 +- .../channel_name_form_field.tsx | 2 +- .../components/create_team/create_team.tsx | 2 +- .../delete_channel_modal.tsx | 6 ++- .../channels/src/components/dot_menu/index.ts | 4 +- .../components/edit_category_modal/index.ts | 6 +-- .../src/components/emoji/emoji_page.tsx | 1 - webapp/channels/src/components/emoji/index.ts | 7 ++- .../forward_post_modal/forward_post_modal.tsx | 8 ++-- .../product_menu/product_menu_list/index.ts | 6 +-- .../product_menu_list/product_menu_list.tsx | 4 +- .../installed_oauth_app.test.tsx | 4 +- .../installed_oauth_app.tsx | 4 +- .../installed_oauth_apps.test.tsx.snap | 28 ++++++++++++ .../installed_oauth_apps.test.tsx | 6 ++- .../installed_oauth_apps.tsx | 8 +++- .../invitation_modal/index.test.tsx | 2 +- .../src/components/invitation_modal/index.tsx | 6 +-- .../invitation_modal/invitation_modal.tsx | 11 ++++- .../channels/src/components/login/login.tsx | 4 +- .../src/components/main_menu/index.tsx | 6 +-- .../src/components/member_list_team/index.ts | 2 +- .../components/more_direct_channels/index.ts | 4 +- .../more_direct_channels.tsx | 6 +-- .../move_thread_modal/move_thread_modal.tsx | 4 +- .../new_channel_modal/new_channel_modal.tsx | 6 +-- .../src/components/permalink_view/actions.ts | 5 ++- .../team_permission_gate/index.ts | 2 +- .../team_permission_gate.tsx | 10 ----- webapp/channels/src/components/post/index.tsx | 8 ++-- .../src/components/post/post_component.tsx | 8 ++-- .../src/components/post_markdown/index.ts | 2 +- .../post_markdown/post_markdown.tsx | 5 ++- .../post_markdown/system_message_helpers.tsx | 8 ++-- .../post_view/channel_intro_message/index.ts | 2 +- .../add_to_channel.tsx | 2 +- .../profile_popover/profile_popover_title.tsx | 2 +- .../components/rename_channel_modal/index.ts | 2 +- .../rename_channel_modal.tsx | 6 ++- .../src/components/rhs_thread/rhs_thread.tsx | 4 +- .../contents/contents.tsx | 8 ++-- .../mobile_sidebar_header/contents/index.ts | 6 +-- .../sidebar/sidebar_channel/index.ts | 2 +- .../sidebar_channel/sidebar_channel.tsx | 4 ++ .../sidebar_channel_menu/index.ts | 1 - .../sidebar_direct_channel/index.ts | 2 +- .../sidebar_group_channel/index.ts | 2 +- .../sidebar/sidebar_header/sidebar_header.tsx | 6 ++- .../sidebar/sidebar_list/sidebar_list.tsx | 4 +- .../sidebar_right/sidebar_right.tsx | 2 +- .../app_command_parser/app_command_parser.ts | 6 ++- .../team_members_dropdown.tsx | 4 +- .../team_members_modal/team_members_modal.tsx | 6 +-- .../team_settings/team_settings.tsx | 4 +- .../unreads_status_handler/index.ts | 3 +- .../unreads_status_handler.tsx | 2 +- .../src/selectors/entities/groups.ts | 2 +- .../src/selectors/entities/roles.ts | 30 ++++++++----- .../src/selectors/entities/teams.ts | 25 ++++++----- webapp/channels/src/utils/post_utils.ts | 3 ++ 82 files changed, 332 insertions(+), 206 deletions(-) diff --git a/webapp/channels/src/actions/views/channel.ts b/webapp/channels/src/actions/views/channel.ts index 9345a2b860..be97a233aa 100644 --- a/webapp/channels/src/actions/views/channel.ts +++ b/webapp/channels/src/actions/views/channel.ts @@ -37,7 +37,7 @@ import { getCurrentRelativeTeamUrl, getCurrentTeam, getCurrentTeamId, - getTeam, + getRelativeTeamUrl, getTeamsList, } from 'mattermost-redux/selectors/entities/teams'; import {getCurrentUserId, getUserByUsername} from 'mattermost-redux/selectors/entities/users'; @@ -103,7 +103,7 @@ export function switchToChannel(channel: Channel & {userId?: string}): ActionFun return async (dispatch, getState) => { const state = getState(); const selectedTeamId = channel.team_id; - const teamUrl = selectedTeamId ? `/${getTeam(state, selectedTeamId).name}` : getCurrentRelativeTeamUrl(state); + const teamUrl = selectedTeamId ? getRelativeTeamUrl(state, selectedTeamId) : getCurrentRelativeTeamUrl(state); if (channel.userId) { const username = channel.userId ? channel.name : channel.display_name; @@ -145,6 +145,9 @@ export function leaveChannel(channelId: string): ActionFuncAsync { let state = getState(); const currentUserId = getCurrentUserId(state); const currentTeam = getCurrentTeam(state); + if (!currentTeam) { + return {data: false}; + } const channel = getChannel(state, channelId); const currentChannelId = getCurrentChannelId(state); diff --git a/webapp/channels/src/actions/views/onboarding_tasks.ts b/webapp/channels/src/actions/views/onboarding_tasks.ts index accedca15b..0c4f4924fc 100644 --- a/webapp/channels/src/actions/views/onboarding_tasks.ts +++ b/webapp/channels/src/actions/views/onboarding_tasks.ts @@ -23,6 +23,10 @@ export function switchToChannels(): ActionFuncAsync { const teamId = getCurrentTeamId(state) || LocalStorageStore.getPreviousTeamId(currentUserId); const team = getTeam(state, teamId || ''); + if (!team) { + return {data: false}; + } + const channel = await getTeamRedirectChannelIfIsAccesible(user, team); const channelName = channel?.name || Constants.DEFAULT_CHANNEL; diff --git a/webapp/channels/src/components/add_groups_to_team_modal/add_groups_to_team_modal.tsx b/webapp/channels/src/components/add_groups_to_team_modal/add_groups_to_team_modal.tsx index f6e88db2f6..75d59db9ea 100644 --- a/webapp/channels/src/components/add_groups_to_team_modal/add_groups_to_team_modal.tsx +++ b/webapp/channels/src/components/add_groups_to_team_modal/add_groups_to_team_modal.tsx @@ -26,7 +26,7 @@ const MAX_SELECTABLE_VALUES = 10; type GroupValue = Value & {member_count?: number}; type Props = { - currentTeamName: string; + currentTeamName?: string; currentTeamId: string; intl: IntlShape; searchTerm: string; @@ -291,7 +291,7 @@ export class AddGroupsToTeamModal extends React.PureComponent { defaultMessage='Add New Groups to {teamName} Team' values={{ teamName: ( - {this.props.currentTeamName} + {this.props.currentTeamName ?? ''} ), }} /> diff --git a/webapp/channels/src/components/add_groups_to_team_modal/index.ts b/webapp/channels/src/components/add_groups_to_team_modal/index.ts index ef37a9597a..b6c1bd1873 100644 --- a/webapp/channels/src/components/add_groups_to_team_modal/index.ts +++ b/webapp/channels/src/components/add_groups_to_team_modal/index.ts @@ -10,7 +10,7 @@ import type {Team} from '@mattermost/types/teams'; import {getGroupsNotAssociatedToTeam, linkGroupSyncable, getAllGroupsAssociatedToTeam} from 'mattermost-redux/actions/groups'; import {getGroupsNotAssociatedToTeam as selectGroupsNotAssociatedToTeam} from 'mattermost-redux/selectors/entities/groups'; -import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; +import {getCurrentTeam, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {setModalSearchTerm} from 'actions/views/search'; @@ -28,17 +28,17 @@ type Props = { function mapStateToProps(state: GlobalState, ownProps: Props) { const searchTerm = state.views.search.modalSearch; - const team = ownProps.team || getCurrentTeam(state) || {}; + const team = ownProps.team || getCurrentTeam(state); - let groups = selectGroupsNotAssociatedToTeam(state, team.id); + let groups = selectGroupsNotAssociatedToTeam(state, team?.id || ''); if (searchTerm) { const regex = RegExp(searchTerm, 'i'); groups = groups.filter((group) => regex.test(group.display_name) || regex.test(group.name)); } return { - currentTeamName: team.display_name, - currentTeamId: team.id, + currentTeamName: team?.display_name, + currentTeamId: team?.id ?? getCurrentTeamId(state), skipCommit: ownProps.skipCommit, onAddCallback: ownProps.onAddCallback, excludeGroups: ownProps.excludeGroups, diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/__snapshots__/channel_details.test.tsx.snap b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/__snapshots__/channel_details.test.tsx.snap index 54c459ed64..7f6f6706d0 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/__snapshots__/channel_details.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/__snapshots__/channel_details.test.tsx.snap @@ -50,7 +50,21 @@ exports[`admin_console/team_channel_settings/channel/ChannelDetails should match onToggleArchive={[Function]} team={ Object { + "allow_open_invite": false, + "allowed_domains": "", + "company_name": "", + "create_at": 0, + "delete_at": 0, + "description": "", "display_name": "test", + "email": "", + "group_constrained": false, + "id": "team_id", + "invite_id": "", + "name": "DN", + "scheme_id": "id", + "type": "O", + "update_at": 0, } } /> @@ -235,7 +249,6 @@ exports[`admin_console/team_channel_settings/channel/ChannelDetails should match isArchived={false} isDisabled={false} onToggleArchive={[Function]} - team={Object {}} /> @@ -557,7 +584,6 @@ exports[`admin_console/team_channel_settings/channel/ChannelDetails should match isArchived={false} isDisabled={false} onToggleArchive={[Function]} - team={Object {}} /> @@ -831,7 +871,6 @@ exports[`admin_console/team_channel_settings/channel/ChannelDetails should match isArchived={false} isDisabled={false} onToggleArchive={[Function]} - team={Object {}} /> { scheme_id: 'id', group_constrained: false, }; - const team: Partial = { + const team = TestHelper.getTeamMock({ display_name: 'test', - }; + }); const teamScheme: Scheme = { id: 'asdf', name: 'asdf', @@ -125,7 +126,7 @@ describe('admin_console/team_channel_settings/channel/ChannelDetails', () => { { scheme_id: 'id', group_constrained: false, }; - const team: Partial = { + const team = TestHelper.getTeamMock({ display_name: 'test', - }; + }); const teamScheme: Scheme = { id: 'asdf', name: 'asdf', @@ -249,7 +250,7 @@ describe('admin_console/team_channel_settings/channel/ChannelDetails', () => { { scheme_id: 'id', group_constrained: false, }; - const team: Partial = { + const team = TestHelper.getTeamMock({ display_name: 'test', - }; + }); const teamScheme: Scheme = { id: 'asdf', name: 'asdf', @@ -374,7 +375,7 @@ describe('admin_console/team_channel_settings/channel/ChannelDetails', () => { ; + team?: Team; groups: Group[]; totalGroups: number; allGroups: Record; @@ -145,7 +145,7 @@ export default class ChannelDetails extends React.PureComponent { if (data.data && data.data.scheme_id) { diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.test.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.test.tsx index 1fada8bf44..27d220c6b4 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.test.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.test.tsx @@ -5,13 +5,14 @@ import {shallow} from 'enzyme'; import React from 'react'; import type {Channel} from '@mattermost/types/channels'; -import type {Team} from '@mattermost/types/teams'; + +import {TestHelper} from 'utils/test_helper'; import {ChannelProfile} from './channel_profile'; describe('admin_console/team_channel_settings/channel/ChannelProfile', () => { test('should match snapshot', () => { - const testTeam: Partial = {display_name: 'test'}; + const testTeam = TestHelper.getTeamMock({display_name: 'test'}); const testChannel: Partial = {display_name: 'test'}; const wrapper = shallow( { }); test('should match snapshot for a shared channel', () => { - const testTeam: Partial = {display_name: 'test'}; + const testTeam = TestHelper.getTeamMock({display_name: 'test'}); const testChannel: Partial = { display_name: 'test', type: 'O', diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.tsx index 09497bb635..877104d5ae 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_profile.tsx @@ -15,7 +15,7 @@ import AdminPanel from 'components/widgets/admin_console/admin_panel'; import './channel_profile.scss'; interface ChannelProfileProps { channel: Partial; - team: Partial; + team?: Team; onToggleArchive?: () => void; isArchived: boolean; isDisabled?: boolean; @@ -71,7 +71,7 @@ export const ChannelProfile = (props: ChannelProfileProps): JSX.Element => { defaultMessage='**Team**' />
- {team.display_name} + {team?.display_name} {sharedBlock}
diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/index.ts b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/index.ts index d75c11f375..0c15318f80 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/index.ts +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/index.ts @@ -63,12 +63,12 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) { const guestAccountsEnabled = config.EnableGuestAccounts === 'true'; const channelID = ownProps.match.params.channel_id; const channel = getChannel(state, channelID) || {}; - const team = getTeam(state, channel.team_id) || {}; + const team = getTeam(state, channel.team_id); const groups = getGroupsAssociatedToChannel(state, channelID); const totalGroups = groups.length; const allGroups = getAllGroups(state); const channelPermissions = getChannelModerations(state, channelID); - const teamScheme = getScheme(state, team.scheme_id); + const teamScheme = team ? getScheme(state, team.scheme_id) : undefined; return { channelID, channel, diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_details.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_details.tsx index d1dfad2421..b0ffc5b0c7 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_details.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_details.tsx @@ -32,7 +32,7 @@ import SaveChangesPanel from '../../save_changes_panel'; export type Props = { teamID: string; - team: Team; + team?: Team; totalGroups: number; groups: Group[]; allGroups: Record; @@ -90,10 +90,10 @@ export default class TeamDetails extends React.PureComponent { const team = props.team; this.state = { groups: props.groups, - syncChecked: Boolean(team.group_constrained), - allAllowedChecked: team.allow_open_invite, - allowedDomainsChecked: Boolean(team.allowed_domains && team.allowed_domains !== ''), - allowedDomains: team.allowed_domains || '', + syncChecked: Boolean(team?.group_constrained), + allAllowedChecked: Boolean(team?.allow_open_invite), + allowedDomainsChecked: Boolean(team?.allowed_domains), + allowedDomains: team?.allowed_domains || '', saving: false, showRemoveConfirmation: false, usersToRemoveCount: 0, @@ -104,21 +104,21 @@ export default class TeamDetails extends React.PureComponent { saveNeeded: false, serverError: undefined, previousServerError: undefined, - isLocalArchived: team.delete_at > 0, + isLocalArchived: team ? team.delete_at > 0 : true, showArchiveConfirmModal: false, }; } componentDidUpdate(prevProps: Props) { const {totalGroups, team} = this.props; - if (prevProps.team.id !== team.id || totalGroups !== prevProps.totalGroups) { + if (prevProps.team?.id !== team?.id || totalGroups !== prevProps.totalGroups) { this.setState({ totalGroups, - syncChecked: Boolean(team.group_constrained), - allAllowedChecked: team.allow_open_invite, - allowedDomainsChecked: Boolean(team.allowed_domains && team.allowed_domains !== ''), - allowedDomains: team.allowed_domains || '', - isLocalArchived: team.delete_at > 0, + syncChecked: Boolean(team?.group_constrained), + allAllowedChecked: Boolean(team?.allow_open_invite), + allowedDomainsChecked: Boolean(team?.allowed_domains), + allowedDomains: team?.allowed_domains || '', + isLocalArchived: team ? team.delete_at > 0 : true, }); } } @@ -141,12 +141,16 @@ export default class TeamDetails extends React.PureComponent { }; handleSubmit = async () => { + const {team, groups: origGroups, teamID, actions} = this.props; + if (!team) { + return; + } + this.setState({showRemoveConfirmation: false, saving: true}); const {groups, allAllowedChecked, allowedDomainsChecked, allowedDomains, syncChecked, usersToAdd, usersToRemove, rolesToUpdate} = this.state; let serverError: JSX.Element | undefined; - const {team, groups: origGroups, teamID, actions} = this.props; if (this.teamToBeArchived()) { let saveNeeded = false; const result = await actions.deleteTeam(team.id); @@ -402,13 +406,13 @@ export default class TeamDetails extends React.PureComponent { teamToBeArchived = () => { const {isLocalArchived} = this.state; - const isServerArchived = this.props.team.delete_at !== 0; + const isServerArchived = this.props.team?.delete_at !== 0; return isLocalArchived && !isServerArchived; }; teamToBeRestored = () => { const {isLocalArchived} = this.state; - const isServerArchived = this.props.team.delete_at !== 0; + const isServerArchived = this.props.team?.delete_at !== 0; return !isLocalArchived && isServerArchived; }; @@ -444,6 +448,11 @@ export default class TeamDetails extends React.PureComponent { render = () => { const {team, isLicensedForLDAPGroups} = this.props; + + if (!team) { + return null; + } + const {totalGroups, saving, saveNeeded, serverError, groups, allAllowedChecked, allowedDomainsChecked, allowedDomains, syncChecked, showRemoveConfirmation, usersToRemoveCount, isLocalArchived, showArchiveConfirmModal} = this.state; const missingGroup = (og: {id: string}) => !groups.find((g) => g.id === og.id); const removedGroups = this.props.groups.filter(missingGroup); diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/index.ts b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/index.ts index faab78eb85..f0eefc9970 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/index.ts +++ b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/index.ts @@ -39,7 +39,7 @@ function mapStateToProps(state: GlobalState, props: Props) { let {usersToAdd} = props; const teamMembers = getMembersInTeams(state)[teamId] || {}; - const team = getTeam(state, teamId) || {}; + const team = getTeam(state, teamId); const config = getConfig(state); const searchTerm = state.views.search.userGridSearch?.term || ''; const filters = state.views.search.userGridSearch?.filters || {}; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/team_members.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/team_members.tsx index 88fc667453..1a1d234991 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/team_members.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/team_members/team_members.tsx @@ -23,7 +23,7 @@ import Constants, {ModalIdentifiers} from 'utils/constants'; type Props = { teamId: string; - team: Team; + team?: Team; filters: GetFilteredUsersStatsOpts; users: UserProfile[]; diff --git a/webapp/channels/src/components/backstage/backstage_controller.tsx b/webapp/channels/src/components/backstage/backstage_controller.tsx index 0560641b97..9115d8a43f 100644 --- a/webapp/channels/src/components/backstage/backstage_controller.tsx +++ b/webapp/channels/src/components/backstage/backstage_controller.tsx @@ -66,7 +66,7 @@ type Props = { /** * Current team. */ - team: Team; + team?: Team; /** * Object from react-router diff --git a/webapp/channels/src/components/backstage/index.ts b/webapp/channels/src/components/backstage/index.ts index 73e9e65e7d..e588d6b284 100644 --- a/webapp/channels/src/components/backstage/index.ts +++ b/webapp/channels/src/components/backstage/index.ts @@ -38,7 +38,7 @@ function mapStateToProps(state: GlobalState) { } } - const canManageTeamIntegrations = (haveITeamPermission(state, team.id, Permissions.MANAGE_SLASH_COMMANDS) || haveITeamPermission(state, team.id, Permissions.MANAGE_OAUTH) || haveITeamPermission(state, team.id, Permissions.MANAGE_INCOMING_WEBHOOKS) || haveITeamPermission(state, team.id, Permissions.MANAGE_OUTGOING_WEBHOOKS)); + const canManageTeamIntegrations = (haveITeamPermission(state, team?.id, Permissions.MANAGE_SLASH_COMMANDS) || haveITeamPermission(state, team?.id, Permissions.MANAGE_OAUTH) || haveITeamPermission(state, team?.id, Permissions.MANAGE_INCOMING_WEBHOOKS) || haveITeamPermission(state, team?.id, Permissions.MANAGE_OUTGOING_WEBHOOKS)); const canManageSystemBots = (haveISystemPermission(state, {permission: Permissions.MANAGE_BOTS}) || haveISystemPermission(state, {permission: Permissions.MANAGE_OTHERS_BOTS})); const canManageIntegrations = canManageTeamIntegrations || canManageSystemBots; diff --git a/webapp/channels/src/components/browse_channels/browse_channels.tsx b/webapp/channels/src/components/browse_channels/browse_channels.tsx index 362e1cfade..43441cff83 100644 --- a/webapp/channels/src/components/browse_channels/browse_channels.tsx +++ b/webapp/channels/src/components/browse_channels/browse_channels.tsx @@ -61,7 +61,7 @@ export type Props = { privateChannels: Channel[]; currentUserId: string; teamId: string; - teamName: string; + teamName?: string; channelsRequestStarted?: boolean; canShowArchivedChannels?: boolean; myChannelMemberships: RelationOneToOne; @@ -103,6 +103,11 @@ export default class BrowseChannels extends React.PureComponent { } componentDidMount() { + if (!this.props.teamId) { + this.loadComplete(); + return; + } + const promises = [ this.props.actions.getChannels(this.props.teamId, 0, CHANNELS_CHUNK_SIZE * 2), ]; @@ -178,7 +183,7 @@ export default class BrowseChannels extends React.PureComponent { this.setState({serverError: result.error.message}); } else { this.props.actions.getChannelsMemberCount([channel.id]); - getHistory().push(getRelativeChannelURL(teamName, channel.name)); + getHistory().push(getRelativeChannelURL(teamName!, channel.name)); this.closeEditRHS(); } @@ -288,6 +293,7 @@ export default class BrowseChannels extends React.PureComponent { render() { const {teamId, channelsRequestStarted, shouldHideJoinedChannels} = this.props; const {search, serverError: serverErrorState, searching} = this.state; + this.activeChannels = this.getActiveChannels(); let serverError; diff --git a/webapp/channels/src/components/browse_channels/index.ts b/webapp/channels/src/components/browse_channels/index.ts index ec7ca1fe11..fd52b4ca67 100644 --- a/webapp/channels/src/components/browse_channels/index.ts +++ b/webapp/channels/src/components/browse_channels/index.ts @@ -12,7 +12,7 @@ import {RequestStatus} from 'mattermost-redux/constants'; import {createSelector} from 'mattermost-redux/selectors/create_selector'; import {getChannelsInCurrentTeam, getMyChannelMemberships, getChannelsMemberCount as getChannelsMemberCountSelector} from 'mattermost-redux/selectors/entities/channels'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; -import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; +import {getCurrentTeam, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {setGlobalItem} from 'actions/storage'; @@ -46,7 +46,7 @@ const getPrivateChannelsSelector = createSelector( ); function mapStateToProps(state: GlobalState) { - const team = getCurrentTeam(state) || {}; + const team = getCurrentTeam(state); const getGlobalItem = makeGetGlobalItem(StoragePrefixes.HIDE_JOINED_CHANNELS, 'false'); return { @@ -54,8 +54,8 @@ function mapStateToProps(state: GlobalState) { archivedChannels: getArchivedOtherChannels(state) || [], privateChannels: getPrivateChannelsSelector(state) || [], currentUserId: getCurrentUserId(state), - teamId: team.id, - teamName: team.name, + teamId: getCurrentTeamId(state), + teamName: team?.name, channelsRequestStarted: state.requests.channels.getChannels.status === RequestStatus.STARTED, canShowArchivedChannels: (getConfig(state).ExperimentalViewArchivedChannels === 'true'), myChannelMemberships: getMyChannelMemberships(state) || {}, diff --git a/webapp/channels/src/components/channel_header_dropdown/menu_items/close_message/close_message.tsx b/webapp/channels/src/components/channel_header_dropdown/menu_items/close_message/close_message.tsx index 2bb056eb39..970d78b267 100644 --- a/webapp/channels/src/components/channel_header_dropdown/menu_items/close_message/close_message.tsx +++ b/webapp/channels/src/components/channel_header_dropdown/menu_items/close_message/close_message.tsx @@ -24,7 +24,7 @@ type Props = { /** * Object with info about currentTeam */ - currentTeam: Team; + currentTeam?: Team; /** * String with info about redirect @@ -86,7 +86,9 @@ export default class CloseMessage extends React.PureComponent { leaveDirectChannel(channel.name); savePreferences(currentUser.id, [{user_id: currentUser.id, category, name, value: 'false'}]); - getHistory().push(`/${currentTeam.name}/channels/${redirectChannel}`); + if (currentTeam) { + getHistory().push(`/${currentTeam.name}/channels/${redirectChannel}`); + } }; render(): React.ReactNode { diff --git a/webapp/channels/src/components/channel_info_rhs/index.ts b/webapp/channels/src/components/channel_info_rhs/index.ts index 50b328e71b..4c2e90a54e 100644 --- a/webapp/channels/src/components/channel_info_rhs/index.ts +++ b/webapp/channels/src/components/channel_info_rhs/index.ts @@ -47,8 +47,8 @@ function mapStateToProps(state: GlobalState) { const isMobile = getIsMobileView(state); const isPrivate = channel.type === Constants.PRIVATE_CHANNEL; - const canManageMembers = haveIChannelPermission(state, currentTeam.id, channel.id, isPrivate ? Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS : Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS); - const canManageProperties = haveIChannelPermission(state, currentTeam.id, channel.id, isPrivate ? Permissions.MANAGE_PRIVATE_CHANNEL_PROPERTIES : Permissions.MANAGE_PUBLIC_CHANNEL_PROPERTIES); + const canManageMembers = haveIChannelPermission(state, currentTeam?.id, channel.id, isPrivate ? Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS : Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS); + const canManageProperties = haveIChannelPermission(state, currentTeam?.id, channel.id, isPrivate ? Permissions.MANAGE_PRIVATE_CHANNEL_PROPERTIES : Permissions.MANAGE_PUBLIC_CHANNEL_PROPERTIES); const channelMembers = getProfilesInCurrentChannel(state); diff --git a/webapp/channels/src/components/channel_invite_modal/channel_invite_modal.tsx b/webapp/channels/src/components/channel_invite_modal/channel_invite_modal.tsx index e9e93d58f3..580d0636ae 100644 --- a/webapp/channels/src/components/channel_invite_modal/channel_invite_modal.tsx +++ b/webapp/channels/src/components/channel_invite_modal/channel_invite_modal.tsx @@ -47,7 +47,7 @@ export type Props = { profilesNotInCurrentTeam: UserProfile[]; profilesFromRecentDMs: UserProfile[]; intl: IntlShape; - membersInTeam: RelationOneToOne; + membersInTeam?: RelationOneToOne; userStatuses: RelationOneToOne; onExited: () => void; channel: Channel; diff --git a/webapp/channels/src/components/channel_invite_modal/index.ts b/webapp/channels/src/components/channel_invite_modal/index.ts index f808818a05..d7560243cf 100644 --- a/webapp/channels/src/components/channel_invite_modal/index.ts +++ b/webapp/channels/src/components/channel_invite_modal/index.ts @@ -5,9 +5,7 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; import type {Dispatch} from 'redux'; -import type {TeamMembership} from '@mattermost/types/teams'; import type {UserProfile} from '@mattermost/types/users'; -import type {RelationOneToOne} from '@mattermost/types/utilities'; import {getTeamStats, getTeamMembersByIds} from 'mattermost-redux/actions/teams'; import {getProfilesNotInChannel, getProfilesInChannel, searchProfiles} from 'mattermost-redux/actions/users'; @@ -50,7 +48,7 @@ function makeMapStateToProps(initialState: GlobalState, initialProps: OwnProps) let profilesNotInCurrentChannel: UserProfile[]; let profilesInCurrentChannel: UserProfile[]; let profilesNotInCurrentTeam: UserProfile[]; - let membersInTeam: RelationOneToOne; + let membersInTeam; if (props.channelId && props.teamId) { profilesNotInCurrentChannel = doGetProfilesNotInChannel(state, props.channelId); @@ -72,7 +70,7 @@ function makeMapStateToProps(initialState: GlobalState, initialProps: OwnProps) const guestAccountsEnabled = config.EnableGuestAccounts === 'true'; const emailInvitationsEnabled = config.EnableEmailInvitations === 'true'; const isLicensed = license && license.IsLicensed === 'true'; - const isGroupConstrained = Boolean(currentTeam.group_constrained); + const isGroupConstrained = Boolean(currentTeam?.group_constrained); const canInviteGuests = !isGroupConstrained && isLicensed && guestAccountsEnabled && haveICurrentTeamPermission(state, Permissions.INVITE_GUEST); const enableCustomUserGroups = isCustomGroupsEnabled(state); diff --git a/webapp/channels/src/components/channel_invite_modal/team_warning_banner/team_warning_banner.tsx b/webapp/channels/src/components/channel_invite_modal/team_warning_banner/team_warning_banner.tsx index c75855364f..6683c732ae 100644 --- a/webapp/channels/src/components/channel_invite_modal/team_warning_banner/team_warning_banner.tsx +++ b/webapp/channels/src/components/channel_invite_modal/team_warning_banner/team_warning_banner.tsx @@ -110,11 +110,11 @@ const TeamWarningBanner = (props: Props) => { mentionName={firstName} /> ), - team: ({team.display_name}), + team: ({team?.display_name}), }, ) ); - }, [guests, formatMessage, getCommaSeparatedUsernames, team.display_name]); + }, [guests, formatMessage, getCommaSeparatedUsernames, team?.display_name]); const getMessage = useCallback(() => { const commaSeparatedUsernames = getCommaSeparatedUsernames(users); @@ -151,7 +151,7 @@ const TeamWarningBanner = (props: Props) => { ), - team: ({team.display_name}), + team: ({team?.display_name}), }, ); } @@ -180,7 +180,7 @@ const TeamWarningBanner = (props: Props) => { mentionName={firstName} /> ), - team: ({team.display_name}), + team: ({team?.display_name}), }, ) ); diff --git a/webapp/channels/src/components/channel_members_rhs/index.ts b/webapp/channels/src/components/channel_members_rhs/index.ts index 3224baa54e..e497d2ed82 100644 --- a/webapp/channels/src/components/channel_members_rhs/index.ts +++ b/webapp/channels/src/components/channel_members_rhs/index.ts @@ -118,7 +118,7 @@ function mapStateToProps(state: GlobalState) { const isPrivate = channel.type === Constants.PRIVATE_CHANNEL; const canManageMembers = haveIChannelPermission( state, - currentTeam.id, + currentTeam?.id, channel.id, isPrivate ? Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS : Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS, ) && !isArchived; diff --git a/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx b/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx index 6d208aa017..d8e8c6d135 100644 --- a/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx +++ b/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx @@ -61,7 +61,7 @@ const ChannelNameFormField = (props: Props): JSX.Element => { const [urlError, setURLError] = useState(''); const [inputCustomMessage, setInputCustomMessage] = useState(null); - const {name: currentTeamName} = useSelector(getCurrentTeam); + const currentTeamName = useSelector(getCurrentTeam)?.name; const teamName = props.team ? props.team.name : currentTeamName; const handleOnDisplayNameChange = useCallback((e: React.ChangeEvent) => { diff --git a/webapp/channels/src/components/create_team/create_team.tsx b/webapp/channels/src/components/create_team/create_team.tsx index 8ffe27e436..fab687b7c0 100644 --- a/webapp/channels/src/components/create_team/create_team.tsx +++ b/webapp/channels/src/components/create_team/create_team.tsx @@ -21,7 +21,7 @@ export type Props = { /* * Object containing information on the current team, used to define BackButton's url */ - currentTeam: Team; + currentTeam?: Team; /* * Object containing information on the current selected channel, used to define BackButton's url diff --git a/webapp/channels/src/components/delete_channel_modal/delete_channel_modal.tsx b/webapp/channels/src/components/delete_channel_modal/delete_channel_modal.tsx index b00552bf09..10d6e609f2 100644 --- a/webapp/channels/src/components/delete_channel_modal/delete_channel_modal.tsx +++ b/webapp/channels/src/components/delete_channel_modal/delete_channel_modal.tsx @@ -15,7 +15,7 @@ import Constants from 'utils/constants'; export type Props = { onExited: () => void; channel: Channel; - currentTeamDetails: {name: string}; + currentTeamDetails?: {name: string}; canViewArchivedChannels?: boolean; penultimateViewedChannelName: string; actions: { @@ -39,7 +39,9 @@ export default class DeleteChannelModal extends React.PureComponent { const channel = useSelector((state: GlobalState) => getChannel(state, {id: post.channel_id})); const currentTeam = useSelector(getCurrentTeam); - const relativePermaLink = useSelector((state: GlobalState) => getPermalinkURL(state, currentTeam.id, post.id)); + const relativePermaLink = useSelector((state: GlobalState) => (currentTeam ? getPermalinkURL(state, currentTeam.id, post.id) : '')); const permaLink = `${getSiteURL()}${relativePermaLink}`; const isPrivateConversation = channel.type !== Constants.OPEN_CHANNEL; @@ -79,11 +79,11 @@ const ForwardPostModal = ({onExited, post, actions}: Props) => { (state: GlobalState) => { const channelId = isPrivateConversation ? channel.id : selectedChannelId; const isDMChannel = selectedChannel?.details?.type === Constants.DM_CHANNEL; - const teamId = isPrivateConversation ? currentTeam.id : selectedChannel?.details?.team_id; + const teamId = isPrivateConversation ? currentTeam?.id : selectedChannel?.details?.team_id; const hasChannelPermission = haveIChannelPermission( state, - teamId || currentTeam.id, + teamId || currentTeam?.id, channelId, Permissions.CREATE_POST, ); @@ -122,7 +122,7 @@ const ForwardPostModal = ({onExited, post, actions}: Props) => { const previewMetaData: PostPreviewMetadata = { post, post_id: post.id, - team_name: currentTeam.name, + team_name: currentTeam?.name || '', channel_display_name: channel.display_name, channel_type: channel.type, channel_id: channel.id, diff --git a/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/index.ts b/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/index.ts index 99d93b4ace..cb0e333582 100644 --- a/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/index.ts +++ b/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/index.ts @@ -36,7 +36,7 @@ import ProductMenuList from './product_menu_list'; function mapStateToProps(state: GlobalState) { const config = getConfig(state); - const currentTeam = getCurrentTeam(state) || {}; + const currentTeam = getCurrentTeam(state); const currentUser = getCurrentUser(state); const appDownloadLink = config.AppDownloadLink || ''; @@ -81,8 +81,8 @@ function mapStateToProps(state: GlobalState) { enablePluginMarketplace, pluginMenuItems: state.plugins.components.MainMenu, siteName, - teamId: currentTeam.id, - teamName: currentTeam.name, + teamId: currentTeam?.id, + teamName: currentTeam?.name, currentUser, firstAdminVisitMarketplaceStatus: getFirstAdminVisitMarketplaceStatus(state), showVisitSystemConsoleTour, diff --git a/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/product_menu_list.tsx b/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/product_menu_list.tsx index 2ab2712f08..7b31f6135f 100644 --- a/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/product_menu_list.tsx +++ b/webapp/channels/src/components/global_header/left_controls/product_menu/product_menu_list/product_menu_list.tsx @@ -36,8 +36,8 @@ import './product_menu_list.scss'; export type Props = { isMobile: boolean; - teamId: string; - teamName: string; + teamId?: string; + teamName?: string; siteName: string; currentUser: UserProfile; appDownloadLink: string; diff --git a/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.test.tsx b/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.test.tsx index a83e26ebb3..2160163516 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.test.tsx +++ b/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.test.tsx @@ -7,9 +7,11 @@ import React from 'react'; import DeleteIntegrationLink from 'components/integrations/delete_integration_link'; import InstalledOAuthApp from 'components/integrations/installed_oauth_app/installed_oauth_app'; +import {TestHelper} from 'utils/test_helper'; + describe('components/integrations/InstalledOAuthApp', () => { const FAKE_SECRET = '***************'; - const team = {name: 'team_name'}; + const team = TestHelper.getTeamMock({name: 'team_name'}); const oauthApp = { id: 'facxd9wpzpbpfp8pad78xj75pr', name: 'testApp', diff --git a/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.tsx b/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.tsx index f30fdb25b6..1da85b5f4e 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.tsx +++ b/webapp/channels/src/components/integrations/installed_oauth_app/installed_oauth_app.tsx @@ -31,7 +31,7 @@ export type InstalledOAuthAppProps = { /** * The team data */ - team: Partial; + team?: Team; /** * The oauthApp data @@ -255,7 +255,7 @@ export default class InstalledOAuthApp extends React.PureComponent + @@ -122,7 +136,21 @@ exports[`components/integrations/InstalledOAuthApps should match snapshot for Ap onRegenerateSecret={[MockFunction]} team={ Object { + "allow_open_invite": false, + "allowed_domains": "", + "company_name": "", + "create_at": 0, + "delete_at": 0, + "description": "", + "display_name": "name", + "email": "", + "group_constrained": false, + "id": "team_id", + "invite_id": "", "name": "test", + "scheme_id": "id", + "type": "O", + "update_at": 0, } } /> diff --git a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.test.tsx b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.test.tsx index 2677aee5eb..bb4f21bd28 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.test.tsx +++ b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.test.tsx @@ -7,6 +7,8 @@ import React from 'react'; import BackstageList from 'components/backstage/components/backstage_list'; import InstalledOAuthApps from 'components/integrations/installed_oauth_apps/installed_oauth_apps'; +import {TestHelper} from 'utils/test_helper'; + describe('components/integrations/InstalledOAuthApps', () => { const oauthApps = { facxd9wpzpbpfp8pad78xj75pr: { @@ -38,9 +40,9 @@ describe('components/integrations/InstalledOAuthApps', () => { }; const baseProps = { - team: { + team: TestHelper.getTeamMock({ name: 'test', - }, + }), oauthApps, canManageOauth: true, actions: { diff --git a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx index 62e8babfef..825d803963 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx +++ b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx @@ -5,6 +5,7 @@ import React from 'react'; import {FormattedMessage} from 'react-intl'; import type {OAuthApp} from '@mattermost/types/integrations'; +import type {Team} from '@mattermost/types/teams'; import type {ActionResult} from 'mattermost-redux/types/actions'; @@ -23,7 +24,7 @@ type Props = { /** * The team data */ - team: {name: string}; + team?: Team; /** * The oauthApps data @@ -123,7 +124,10 @@ export default class InstalledOAuthApps extends React.PureComponent { const props = mapStateToProps(testState, {channelToInvite: testChannel}); - expect(props.currentTeam.id).toBe(testChannel.team_id); + expect(props.currentTeam?.id).toBe(testChannel.team_id); }); }); diff --git a/webapp/channels/src/components/invitation_modal/index.tsx b/webapp/channels/src/components/invitation_modal/index.tsx index 25dc6164c2..25e00fa274 100644 --- a/webapp/channels/src/components/invitation_modal/index.tsx +++ b/webapp/channels/src/components/invitation_modal/index.tsx @@ -63,14 +63,14 @@ export function mapStateToProps(state: GlobalState, props: OwnProps) { return false; } if (channel.type === Constants.PRIVATE_CHANNEL) { - return haveIChannelPermission(state, currentTeam.id, channel.id, Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS); + return haveIChannelPermission(state, currentTeam?.id, channel.id, Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS); } - return haveIChannelPermission(state, currentTeam.id, channel.id, Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS); + return haveIChannelPermission(state, currentTeam?.id, channel.id, Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS); }); const guestAccountsEnabled = config.EnableGuestAccounts === 'true'; const emailInvitationsEnabled = config.EnableEmailInvitations === 'true'; const isEnterpriseReady = config.BuildEnterpriseReady === 'true'; - const isGroupConstrained = Boolean(currentTeam.group_constrained); + const isGroupConstrained = Boolean(currentTeam?.group_constrained); const canInviteGuests = !isGroupConstrained && isEnterpriseReady && guestAccountsEnabled && haveICurrentTeamPermission(state, Permissions.INVITE_GUEST); const isCloud = license.Cloud === 'true'; diff --git a/webapp/channels/src/components/invitation_modal/invitation_modal.tsx b/webapp/channels/src/components/invitation_modal/invitation_modal.tsx index 7b316a5500..0ce4ae2bb4 100644 --- a/webapp/channels/src/components/invitation_modal/invitation_modal.tsx +++ b/webapp/channels/src/components/invitation_modal/invitation_modal.tsx @@ -59,7 +59,7 @@ export type Props = { message: string, ) => Promise>; }; - currentTeam: Team; + currentTeam?: Team; currentChannel: Channel; townSquareDisplayName: string; invitableChannels: Channel[]; @@ -159,6 +159,9 @@ export class InvitationModal extends React.PureComponent { }; invite = async () => { + if (!this.props.currentTeam) { + return; + } const roleForTrackFlow = getRoleForTrackFlow(); const inviteAs = this.state.invite.inviteType; if (inviteAs === InviteType.MEMBER && this.props.isCloud) { @@ -246,7 +249,7 @@ export class InvitationModal extends React.PureComponent { })); }; - debouncedSearchChannels = debounce((term) => this.props.actions.searchChannels(this.props.currentTeam.id, term), 150); + debouncedSearchChannels = debounce((term) => this.props.currentTeam && this.props.actions.searchChannels(this.props.currentTeam.id, term), 150); channelsLoader = async (value: string) => { if (!value) { @@ -357,6 +360,10 @@ export class InvitationModal extends React.PureComponent { }; render() { + if (!this.props.currentTeam) { + return null; + } + let view = ( { const initializing = useSelector((state: GlobalState) => state.requests.users.logout.status === RequestStatus.SUCCESS || !state.storage.initialized); const currentUser = useSelector(getCurrentUser); const experimentalPrimaryTeam = useSelector((state: GlobalState) => (ExperimentalPrimaryTeam ? getTeamByName(state, ExperimentalPrimaryTeam) : undefined)); - const experimentalPrimaryTeamMember = useSelector((state: GlobalState) => getMyTeamMember(state, experimentalPrimaryTeam?.id ?? '')); + const experimentalPrimaryTeamMember = useSelector((state: GlobalState) => (experimentalPrimaryTeam ? getMyTeamMember(state, experimentalPrimaryTeam.id) : undefined)); const onboardingFlowEnabled = useSelector(getIsOnboardingFlowEnabled); const loginIdInput = useRef(null); @@ -666,7 +666,7 @@ const Login = ({onCustomizeHeader}: LoginProps) => { history.push(redirectTo); } else if (team) { history.push(`/${team.name}`); - } else if (experimentalPrimaryTeamMember.team_id) { + } else if (experimentalPrimaryTeamMember?.team_id) { // Only set experimental team if user is on that team history.push(`/${ExperimentalPrimaryTeam}`); } else if (onboardingFlowEnabled) { diff --git a/webapp/channels/src/components/main_menu/index.tsx b/webapp/channels/src/components/main_menu/index.tsx index b5fe13b1f7..3236a53bab 100644 --- a/webapp/channels/src/components/main_menu/index.tsx +++ b/webapp/channels/src/components/main_menu/index.tsx @@ -76,11 +76,11 @@ function mapStateToProps(state: GlobalState) { pluginMenuItems: state.plugins.components.MainMenu, moreTeamsToJoin, siteName, - teamId: currentTeam.id, - teamName: currentTeam.name, + teamId: currentTeam?.id, + teamName: currentTeam?.name, currentUser, isMentionSearch: rhsState === RHSStates.MENTION, - teamIsGroupConstrained: Boolean(currentTeam.group_constrained), + teamIsGroupConstrained: Boolean(currentTeam?.group_constrained), isLicensedForLDAPGroups: state.entities.general.license.LDAPGroups === 'true', guestAccessEnabled: config.EnableGuestAccounts === 'true', canInviteTeamMember, diff --git a/webapp/channels/src/components/member_list_team/index.ts b/webapp/channels/src/components/member_list_team/index.ts index 796cfb5c41..8da03e6d24 100644 --- a/webapp/channels/src/components/member_list_team/index.ts +++ b/webapp/channels/src/components/member_list_team/index.ts @@ -21,7 +21,7 @@ import type {GlobalState} from 'types/store'; import MemberListTeam from './member_list_team'; type Props = { - teamId: string; + teamId?: string; } function mapStateToProps(state: GlobalState, ownProps: Props) { diff --git a/webapp/channels/src/components/more_direct_channels/index.ts b/webapp/channels/src/components/more_direct_channels/index.ts index f5b6d62f6e..a3e4b5dc89 100644 --- a/webapp/channels/src/components/more_direct_channels/index.ts +++ b/webapp/channels/src/components/more_direct_channels/index.ts @@ -71,8 +71,8 @@ const makeMapStateToProps = () => { const stats = getTotalUsersStatsSelector(state) || {total_users_count: 0}; return { - currentTeamId: team.id, - currentTeamName: team.name, + currentTeamId: team?.id, + currentTeamName: team?.name, searchTerm, users, currentChannelMembers, diff --git a/webapp/channels/src/components/more_direct_channels/more_direct_channels.tsx b/webapp/channels/src/components/more_direct_channels/more_direct_channels.tsx index ceee0a6f4a..2693ab84fc 100644 --- a/webapp/channels/src/components/more_direct_channels/more_direct_channels.tsx +++ b/webapp/channels/src/components/more_direct_channels/more_direct_channels.tsx @@ -27,8 +27,8 @@ import type { export type Props = { currentUserId: string; - currentTeamId: string; - currentTeamName: string; + currentTeamId?: string; + currentTeamName?: string; searchTerm: string; users: UserProfile[]; totalCount: number; @@ -239,7 +239,7 @@ export default class MoreDirectChannels extends React.PureComponent { + this.props.actions.getProfilesInTeam(this.props.currentTeamId || '', pageNum, USERS_PER_PAGE * 2).then(() => { this.setUsersLoadingState(false); }); } diff --git a/webapp/channels/src/components/move_thread_modal/move_thread_modal.tsx b/webapp/channels/src/components/move_thread_modal/move_thread_modal.tsx index 9a53fc53d1..7429a24437 100644 --- a/webapp/channels/src/components/move_thread_modal/move_thread_modal.tsx +++ b/webapp/channels/src/components/move_thread_modal/move_thread_modal.tsx @@ -103,11 +103,11 @@ const MoveThreadModal = ({onExited, post, actions}: Props) => { const previewMetaData: PostPreviewMetadata = useMemo(() => ({ post, post_id: post.id, - team_name: currentTeam.name, + team_name: currentTeam?.name || '', channel_display_name: originalChannel.display_name, channel_type: originalChannel.type, channel_id: originalChannel.id, - }), [post, currentTeam.name, originalChannel.display_name, originalChannel.type, originalChannel.id]); + }), [post, currentTeam?.name, originalChannel.display_name, originalChannel.type, originalChannel.id]); const notificationText = formatMessage({ id: 'move_thread_modal.notification.dm_or_gm', diff --git a/webapp/channels/src/components/new_channel_modal/new_channel_modal.tsx b/webapp/channels/src/components/new_channel_modal/new_channel_modal.tsx index a171538b1a..7713343aca 100644 --- a/webapp/channels/src/components/new_channel_modal/new_channel_modal.tsx +++ b/webapp/channels/src/components/new_channel_modal/new_channel_modal.tsx @@ -59,7 +59,7 @@ const NewChannelModal = () => { const intl = useIntl(); const {formatMessage} = intl; - const {id: currentTeamId} = useSelector(getCurrentTeam); + const currentTeamId = useSelector(getCurrentTeam)?.id; const canCreatePublicChannel = useSelector((state: GlobalState) => (currentTeamId ? haveICurrentChannelPermission(state, Permissions.CREATE_PUBLIC_CHANNEL) : false)); const canCreatePrivateChannel = useSelector((state: GlobalState) => (currentTeamId ? haveICurrentChannelPermission(state, Permissions.CREATE_PRIVATE_CHANNEL) : false)); @@ -88,7 +88,7 @@ const NewChannelModal = () => { }, []); const handleOnModalConfirm = async () => { - if (!canCreate) { + if (!canCreate || !currentTeamId) { return; } @@ -135,7 +135,7 @@ const NewChannelModal = () => { }; const addBoardToChannel = async (channelId: string) => { - if (!createBoardFromChannelPlugin) { + if (!createBoardFromChannelPlugin || !currentTeamId) { return false; } if (!actionFromPluggable) { diff --git a/webapp/channels/src/components/permalink_view/actions.ts b/webapp/channels/src/components/permalink_view/actions.ts index d9a423f106..0d5e6fae7b 100644 --- a/webapp/channels/src/components/permalink_view/actions.ts +++ b/webapp/channels/src/components/permalink_view/actions.ts @@ -63,7 +63,7 @@ function focusReplyPost(post: Post, channel: Channel, teamId: string, returnTo: const team = getTeam(state, channel.team_id || teamId); const currentChannel = getCurrentChannel(state); - const sameTeam = currentChannel && currentChannel.team_id === team.id; + const sameTeam = currentChannel && currentChannel.team_id === team?.id; const {skipRedirectReplyPermalink} = option; @@ -100,6 +100,9 @@ export function focusPost(postId: string, returnTo = '', currentUserId: string, const state = getState(); const currentTeam = getCurrentTeam(state); + if (!currentTeam) { + return; + } if (!postInfo.has_joined_channel) { // Prompt system admin before joining the private channel diff --git a/webapp/channels/src/components/permissions_gates/team_permission_gate/index.ts b/webapp/channels/src/components/permissions_gates/team_permission_gate/index.ts index 165d6f18db..9be96e929b 100644 --- a/webapp/channels/src/components/permissions_gates/team_permission_gate/index.ts +++ b/webapp/channels/src/components/permissions_gates/team_permission_gate/index.ts @@ -10,7 +10,7 @@ import type {GlobalState} from 'types/store'; import TeamPermissionGate from './team_permission_gate'; type Props = { - teamId: string; + teamId?: string; permissions: string[]; } diff --git a/webapp/channels/src/components/permissions_gates/team_permission_gate/team_permission_gate.tsx b/webapp/channels/src/components/permissions_gates/team_permission_gate/team_permission_gate.tsx index 6864666005..02f5c213fc 100644 --- a/webapp/channels/src/components/permissions_gates/team_permission_gate/team_permission_gate.tsx +++ b/webapp/channels/src/components/permissions_gates/team_permission_gate/team_permission_gate.tsx @@ -5,16 +5,6 @@ import React from 'react'; type Props = { - /** - * Team to check the permission - */ - teamId?: string; - - /** - * Permissions enough to pass the gate (binary OR) - */ - permissions: string[]; - /** * Has permission */ diff --git a/webapp/channels/src/components/post/index.tsx b/webapp/channels/src/components/post/index.tsx index 180207d181..05f4ab7dbc 100644 --- a/webapp/channels/src/components/post/index.tsx +++ b/webapp/channels/src/components/post/index.tsx @@ -133,8 +133,8 @@ function makeMapStateToProps() { const currentTeam = getCurrentTeam(state); const team = getTeam(state, channel.team_id); - let teamName = currentTeam.name; - let teamDisplayName = ''; + let teamName = currentTeam?.name; + let teamDisplayName; const memberships = getTeamMemberships(state); const isDMorGM = channel.type === General.DM_CHANNEL || channel.type === General.GM_CHANNEL; @@ -145,10 +145,10 @@ function makeMapStateToProps() { memberships && Object.values(memberships).length > 1 // Not show if the user only belongs to one team ) { teamDisplayName = team?.display_name; - teamName = team?.name || currentTeam.name; + teamName = team?.name || currentTeam?.name; } - const canReply = isDMorGM || (channel.team_id === currentTeam.id); + const canReply = isDMorGM || (channel.team_id === currentTeam?.id); const directTeammate = getDirectTeammate(state, channel.id); const previewCollapsed = get( diff --git a/webapp/channels/src/components/post/post_component.tsx b/webapp/channels/src/components/post/post_component.tsx index df6414c43c..c4add51e29 100644 --- a/webapp/channels/src/components/post/post_component.tsx +++ b/webapp/channels/src/components/post/post_component.tsx @@ -55,7 +55,7 @@ import PostUserProfile from './user_profile'; export type Props = { post: Post; - currentTeam: Team; + currentTeam?: Team; team?: Team; currentUserId: string; compactDisplay?: boolean; @@ -128,7 +128,7 @@ const PostComponent = (props: Props): JSX.Element => { const isRHS = props.location === Locations.RHS_ROOT || props.location === Locations.RHS_COMMENT || props.location === Locations.SEARCH; const postRef = useRef(null); const postHeaderRef = useRef(null); - const teamId = props.team?.id || props.currentTeam.id; + const teamId = props.team?.id ?? props.currentTeam?.id ?? ''; const [hover, setHover] = useState(false); const [a11yActive, setA11y] = useState(false); @@ -391,12 +391,12 @@ const PostComponent = (props: Props): JSX.Element => { }, [post, props.actions, props.actions.selectPostFromRightHandSideSearch]); const handleThreadClick = useCallback((e: React.MouseEvent) => { - if (props.currentTeam.id === teamId) { + if (props.currentTeam?.id === teamId) { handleCommentClick(e); } else { handleJumpClick(e); } - }, [handleCommentClick, handleJumpClick, props.currentTeam.id, teamId]); + }, [handleCommentClick, handleJumpClick, props.currentTeam?.id, teamId]); const postClass = classNames('post__body', {'post--edited': PostUtils.isEdited(post), 'search-item-snippet': isSearchResultItem}); diff --git a/webapp/channels/src/components/post_markdown/index.ts b/webapp/channels/src/components/post_markdown/index.ts index 32345947c0..18d50ff40f 100644 --- a/webapp/channels/src/components/post_markdown/index.ts +++ b/webapp/channels/src/components/post_markdown/index.ts @@ -61,7 +61,7 @@ function makeMapStateToProps() { return (state: GlobalState, ownProps: OwnProps) => { const channel = getChannel(state, ownProps.channelId); - const currentTeam = getCurrentTeam(state) || {}; + const currentTeam = getCurrentTeam(state); const license = getLicense(state); const subscriptionProduct = getSubscriptionProduct(state); diff --git a/webapp/channels/src/components/post_markdown/post_markdown.tsx b/webapp/channels/src/components/post_markdown/post_markdown.tsx index 8fd8e13375..89a53b9c16 100644 --- a/webapp/channels/src/components/post_markdown/post_markdown.tsx +++ b/webapp/channels/src/components/post_markdown/post_markdown.tsx @@ -66,7 +66,7 @@ export default class PostMarkdown extends React.PureComponent { if (this.props.post) { const renderedSystemMessage = renderSystemMessage(this.props.post, - this.props.currentTeam, + this.props.currentTeam?.name ?? '', this.props.channel, this.props.hideGuestTags, this.props.isUserCanManageMembers, @@ -78,6 +78,9 @@ export default class PostMarkdown extends React.PureComponent { } if (this.props.post && this.props.post.type === Posts.POST_TYPES.REMINDER) { + if (!this.props.currentTeam) { + return null; + } const renderedSystemBotMessage = renderReminderSystemBotMessage(this.props.post, this.props.currentTeam); return
{renderedSystemBotMessage}
; } diff --git a/webapp/channels/src/components/post_markdown/system_message_helpers.tsx b/webapp/channels/src/components/post_markdown/system_message_helpers.tsx index 720c20907a..f63a7c3456 100644 --- a/webapp/channels/src/components/post_markdown/system_message_helpers.tsx +++ b/webapp/channels/src/components/post_markdown/system_message_helpers.tsx @@ -389,10 +389,10 @@ const systemMessageRenderers = { [Posts.POST_TYPES.ME]: renderMeMessage, }; -export function renderSystemMessage(post: Post, currentTeam: Team, channel: Channel, hideGuestTags: boolean, isUserCanManageMembers?: boolean, isMilitaryTime?: boolean, timezone?: string): ReactNode { +export function renderSystemMessage(post: Post, currentTeamName: string, channel: Channel, hideGuestTags: boolean, isUserCanManageMembers?: boolean, isMilitaryTime?: boolean, timezone?: string): ReactNode { const isEphemeral = isPostEphemeral(post); if (isEphemeral && post.props?.type === Posts.POST_TYPES.REMINDER) { - return renderReminderACKMessage(post, currentTeam, Boolean(isMilitaryTime), timezone); + return renderReminderACKMessage(post, currentTeamName, Boolean(isMilitaryTime), timezone); } if (post.props && post.props.add_channel_member) { if (channel && (channel.type === General.PRIVATE_CHANNEL || channel.type === General.OPEN_CHANNEL) && @@ -439,9 +439,9 @@ export function renderSystemMessage(post: Post, currentTeam: Team, channel: Chan return null; } -function renderReminderACKMessage(post: Post, currentTeam: Team, isMilitaryTime: boolean, timezone?: string): ReactNode { +function renderReminderACKMessage(post: Post, currentTeamName: string, isMilitaryTime: boolean, timezone?: string): ReactNode { const username = renderUsername(post.props.username); - const teamUrl = `${getSiteURL()}/${post.props.team_name || currentTeam.name}`; + const teamUrl = `${getSiteURL()}/${post.props.team_name || currentTeamName}`; const link = `${teamUrl}/pl/${post.props.post_id}`; const permaLink = renderFormattedText(`[${link}](${link})`); const localTime = new Date(post.props.target_time * 1000); diff --git a/webapp/channels/src/components/post_view/channel_intro_message/index.ts b/webapp/channels/src/components/post_view/channel_intro_message/index.ts index 2774cd88cb..d78186fa66 100644 --- a/webapp/channels/src/components/post_view/channel_intro_message/index.ts +++ b/webapp/channels/src/components/post_view/channel_intro_message/index.ts @@ -47,7 +47,7 @@ function mapStateToProps(state: GlobalState) { enableUserCreation, isReadOnly, isFavorite: isCurrentChannelFavorite(state), - teamIsGroupConstrained: Boolean(team.group_constrained), + teamIsGroupConstrained: Boolean(team?.group_constrained), creatorName: getDisplayNameByUser(state, creator), teammate, teammateName: getDisplayNameByUser(state, teammate), diff --git a/webapp/channels/src/components/profile_popover/profile_popover_actions/add_to_channel.tsx b/webapp/channels/src/components/profile_popover/profile_popover_actions/add_to_channel.tsx index ae3cf8fb75..f190ecafb6 100644 --- a/webapp/channels/src/components/profile_popover/profile_popover_actions/add_to_channel.tsx +++ b/webapp/channels/src/components/profile_popover/profile_popover_actions/add_to_channel.tsx @@ -29,7 +29,7 @@ type Props = { function getIsInCurrentTeam(state: GlobalState, userId: string) { const team = getCurrentTeam(state); - const teamMember = getTeamMember(state, team.id, userId); + const teamMember = team ? getTeamMember(state, team.id, userId) : undefined; return Boolean(teamMember) && teamMember?.delete_at === 0; } diff --git a/webapp/channels/src/components/profile_popover/profile_popover_title.tsx b/webapp/channels/src/components/profile_popover/profile_popover_title.tsx index 3f342982d2..db305ff0c4 100644 --- a/webapp/channels/src/components/profile_popover/profile_popover_title.tsx +++ b/webapp/channels/src/components/profile_popover/profile_popover_title.tsx @@ -33,7 +33,7 @@ type Props = { function getIsTeamAdmin(state: GlobalState, userId: string) { const team = getCurrentTeam(state); - const teamMember = getTeamMember(state, team.id, userId); + const teamMember = team ? getTeamMember(state, team.id, userId) : undefined; return Boolean(teamMember && teamMember.scheme_admin); } diff --git a/webapp/channels/src/components/rename_channel_modal/index.ts b/webapp/channels/src/components/rename_channel_modal/index.ts index 8bb91d8456..a18a61a59a 100644 --- a/webapp/channels/src/components/rename_channel_modal/index.ts +++ b/webapp/channels/src/components/rename_channel_modal/index.ts @@ -20,7 +20,7 @@ const mapStateToPropsRenameChannel = createSelector( (state: GlobalState) => { const currentTeamId = state.entities.teams.currentTeamId; const team = getTeam(state, currentTeamId); - const currentTeamUrl = `${getSiteURL()}/${team.name}`; + const currentTeamUrl = `${getSiteURL()}/${team ? team.name : ''}`; return { currentTeamUrl, team, diff --git a/webapp/channels/src/components/rename_channel_modal/rename_channel_modal.tsx b/webapp/channels/src/components/rename_channel_modal/rename_channel_modal.tsx index f5916e63f4..8be7bd99ba 100644 --- a/webapp/channels/src/components/rename_channel_modal/rename_channel_modal.tsx +++ b/webapp/channels/src/components/rename_channel_modal/rename_channel_modal.tsx @@ -56,7 +56,7 @@ type Props = { /** * Object with info about current team */ - team: Team; + team?: Team; /** * String with the current team URL @@ -190,7 +190,9 @@ export class RenameChannelModal extends React.PureComponent { onSaveSuccess = () => { this.handleHide(); this.unsetError(); - getHistory().push('/' + this.props.team.name + '/channels/' + this.state.channelName); + if (this.props.team) { + getHistory().push('/' + this.props.team.name + '/channels/' + this.state.channelName); + } }; handleCancel = (e?: MouseEvent) => { diff --git a/webapp/channels/src/components/rhs_thread/rhs_thread.tsx b/webapp/channels/src/components/rhs_thread/rhs_thread.tsx index cdf8d3be17..f1f891504e 100644 --- a/webapp/channels/src/components/rhs_thread/rhs_thread.tsx +++ b/webapp/channels/src/components/rhs_thread/rhs_thread.tsx @@ -16,7 +16,7 @@ import ThreadViewer from 'components/threading/thread_viewer'; import type {FakePost, RhsState} from 'types/store/rhs'; type Props = { - currentTeam: Team; + currentTeam?: Team; posts: Post[]; channel: Channel | null; selected: Post | FakePost; @@ -35,7 +35,7 @@ const RhsThread = ({ const dispatch = useDispatch(); useEffect(() => { - if (channel?.team_id && channel.team_id !== currentTeam.id) { + if (channel?.team_id && channel.team_id !== currentTeam?.id) { // if team-scoped and mismatched team, close rhs dispatch(closeRightHandSide()); } diff --git a/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/contents.tsx b/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/contents.tsx index 7b9a143c80..a4b198fb29 100644 --- a/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/contents.tsx +++ b/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/contents.tsx @@ -30,10 +30,10 @@ const VerticalStack = styled.div` `; type Props = { - teamDescription: string; - teamId: string; + teamDescription?: string; + teamId?: string; currentUser: UserProfile; - teamDisplayName: string; + teamDisplayName?: string; actions: Actions; }; @@ -52,7 +52,7 @@ export default class Contents extends React.PureComponent { }; render() { - if (!this.props.currentUser) { + if (!this.props.currentUser || !this.props.teamId) { return null; } diff --git a/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/index.ts b/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/index.ts index 3fa23be4ab..7fa4eca19b 100644 --- a/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/index.ts +++ b/webapp/channels/src/components/sidebar/mobile_sidebar_header/contents/index.ts @@ -20,9 +20,9 @@ function mapStateToProps(state: GlobalState) { return { currentUser, - teamDescription: currentTeam.description, - teamDisplayName: currentTeam.display_name, - teamId: currentTeam.id, + teamDescription: currentTeam?.description, + teamDisplayName: currentTeam?.display_name, + teamId: currentTeam?.id, }; } diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/index.ts b/webapp/channels/src/components/sidebar/sidebar_channel/index.ts index 7bbc6d78c3..9a0352d9d1 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/index.ts +++ b/webapp/channels/src/components/sidebar/sidebar_channel/index.ts @@ -42,7 +42,7 @@ function makeMapStateToProps() { return { channel, isCurrentChannel: channel.id === currentChannelId, - currentTeamName: currentTeam.name, + currentTeamName: currentTeam?.name, unreadMentions: unreadCount.mentions, isUnread: unreadCount.showUnread, draggingState: getDraggingState(state), diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.tsx b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.tsx index ff72916d8f..94a2f05f09 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.tsx +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.tsx @@ -33,6 +33,10 @@ function SidebarChannel({ }: Props) { const [show, setShow] = useState(true); + if (!currentTeamName) { + return null; + } + function isCollapsed() { return isCategoryDragged || (isCategoryCollapsed && !isUnread && !isCurrentChannel); } diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/index.ts b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/index.ts index 8385e02073..fa82bfbfa6 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/index.ts +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/index.ts @@ -52,7 +52,6 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) { } return { - currentTeamId: currentTeam.id, currentUserId: getCurrentUserId(state), categories, currentCategory, diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_direct_channel/index.ts b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_direct_channel/index.ts index 850d0e87f2..a9c8e46a99 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_direct_channel/index.ts +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_direct_channel/index.ts @@ -26,7 +26,7 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) { const teammate = getUser(state, ownProps.channel.teammate_id!); const currentUser = getCurrentUser(state); const currentTeam = getCurrentTeam(state); - const redirectChannel = getRedirectChannelNameForTeam(state, currentTeam.id); + const redirectChannel = currentTeam ? getRedirectChannelNameForTeam(state, currentTeam.id) : ''; const currentChannelId = getCurrentChannelId(state); const active = ownProps.channel.id === currentChannelId; diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_group_channel/index.ts b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_group_channel/index.ts index 18502617c1..d1794e140f 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_group_channel/index.ts +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_group_channel/index.ts @@ -25,7 +25,7 @@ function makeMapStateToProps() { return (state: GlobalState, ownProps: OwnProps) => { const currentUserId = getCurrentUserId(state); const currentTeam = getCurrentTeam(state); - const redirectChannel = getRedirectChannelNameForTeam(state, currentTeam.id); + const redirectChannel = currentTeam ? getRedirectChannelNameForTeam(state, currentTeam.id) : ''; const currentChannelId = getCurrentChannelId(state); const membersCount = getMemberCount(state, ownProps.channel); const active = ownProps.channel.id === currentChannelId; diff --git a/webapp/channels/src/components/sidebar/sidebar_header/sidebar_header.tsx b/webapp/channels/src/components/sidebar/sidebar_header/sidebar_header.tsx index 66d20c2799..929dfa37db 100644 --- a/webapp/channels/src/components/sidebar/sidebar_header/sidebar_header.tsx +++ b/webapp/channels/src/components/sidebar/sidebar_header/sidebar_header.tsx @@ -97,7 +97,7 @@ export type Props = { canCreateCustomGroups: boolean; } -const SidebarHeader: React.FC = (props: Props): JSX.Element => { +const SidebarHeader = (props: Props) => { const dispatch = useDispatch(); const currentTeam = useSelector((state: GlobalState) => getCurrentTeam(state)); const showCreateTutorialTip = useShowOnboardingTutorialStep(OnboardingTourSteps.CREATE_AND_JOIN_CHANNELS); @@ -115,6 +115,10 @@ const SidebarHeader: React.FC = (props: Props): JSX.Element => { setMenuToggled(!menuToggled); }; + if (!currentTeam) { + return null; + } + return ( { this.props.actions.moveChannelsInSidebar(result.destination.droppableId, result.destination.index, result.draggableId); trackEvent('ui', 'ui_sidebar_dragdrop_dropped_channel'); } else if (result.type === 'SIDEBAR_CATEGORY') { - this.props.actions.moveCategory(this.props.currentTeam.id, result.draggableId, result.destination.index); + this.props.actions.moveCategory(this.props.currentTeam!.id, result.draggableId, result.destination.index); trackEvent('ui', 'ui_sidebar_dragdrop_dropped_category'); } } diff --git a/webapp/channels/src/components/sidebar_right/sidebar_right.tsx b/webapp/channels/src/components/sidebar_right/sidebar_right.tsx index 058e4f18af..606931e885 100644 --- a/webapp/channels/src/components/sidebar_right/sidebar_right.tsx +++ b/webapp/channels/src/components/sidebar_right/sidebar_right.tsx @@ -32,7 +32,7 @@ export type Props = { isExpanded: boolean; isOpen: boolean; channel: Channel; - team: Team; + team?: Team; teamId: Team['id']; productId: ProductIdentifier; postRightVisible: boolean; diff --git a/webapp/channels/src/components/suggestion/command_provider/app_command_parser/app_command_parser.ts b/webapp/channels/src/components/suggestion/command_provider/app_command_parser/app_command_parser.ts index 8f5852dcfd..ee350afcb1 100644 --- a/webapp/channels/src/components/suggestion/command_provider/app_command_parser/app_command_parser.ts +++ b/webapp/channels/src/components/suggestion/command_provider/app_command_parser/app_command_parser.ts @@ -1329,7 +1329,11 @@ export class AppCommandParser { const getChannel = async (channelName: string) => { let channel = selectChannelByName(this.store.getState(), channelName); if (!channel) { - const dispatchResult = await this.store.dispatch(getChannelByNameAndTeamName(getCurrentTeam(this.store.getState()).name, channelName) as any); + const team = getCurrentTeam(this.store.getState()); + if (!team) { + return null; + } + const dispatchResult = await this.store.dispatch(getChannelByNameAndTeamName(team.name, channelName) as any); if ('error' in dispatchResult) { return null; } diff --git a/webapp/channels/src/components/team_members_dropdown/team_members_dropdown.tsx b/webapp/channels/src/components/team_members_dropdown/team_members_dropdown.tsx index 3a495a0b73..0d0d089ebc 100644 --- a/webapp/channels/src/components/team_members_dropdown/team_members_dropdown.tsx +++ b/webapp/channels/src/components/team_members_dropdown/team_members_dropdown.tsx @@ -26,7 +26,7 @@ type Props = { currentUser: UserProfile; teamMember: TeamMembership; teamUrl: string; - currentTeam: Team; + currentTeam?: Team; index: number; totalUsers: number; collapsedThreads: ReturnType; @@ -190,7 +190,7 @@ export default class TeamMembersDropdown extends React.PureComponent void; onLoad?: () => void; actions: { @@ -90,7 +90,7 @@ export default class TeamMembersModal extends React.PureComponent />