mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Migrating other 2 files from javascript to typescript (#29435)
* feat: Add initial store configuration for webapp channels * refactor: Convert store/index.js to TypeScript with type definitions * test: Add initial test file for store index * refactor: Convert index.test.js to TypeScript with type annotations * Removing old files * Applying linter fixes * Fixing some of the types errors * fix: Type mock implementation of getState in global_actions.test.ts * test: Add missing GlobalState import in global_actions.test.ts * fix: Resolve TypeScript mock implementation error in global_actions.test.ts * Some fixes * Address CI problems * Installing zen-observable types * Addressing PR review comment * Addressing PR review comment * Addressing PR review comment * Addressing PR review comment * Addressing PR review comment * Simpliying things * Fixing CI * Fixing types
This commit is contained in:
parent
90814564ff
commit
9b87970c99
@ -140,6 +140,7 @@
|
|||||||
"@types/shallow-equals": "1.0.3",
|
"@types/shallow-equals": "1.0.3",
|
||||||
"@types/styled-components": "5.1.32",
|
"@types/styled-components": "5.1.32",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
|
"@types/zen-observable": "0.8.7",
|
||||||
"copy-webpack-plugin": "11.0.0",
|
"copy-webpack-plugin": "11.0.0",
|
||||||
"emoji-datasource": "6.1.1",
|
"emoji-datasource": "6.1.1",
|
||||||
"emoji-datasource-apple": "6.1.1",
|
"emoji-datasource-apple": "6.1.1",
|
||||||
|
@ -13,6 +13,8 @@ import reduxStore from 'stores/redux_store';
|
|||||||
import mockStore from 'tests/test_store';
|
import mockStore from 'tests/test_store';
|
||||||
import {getHistory} from 'utils/browser_history';
|
import {getHistory} from 'utils/browser_history';
|
||||||
|
|
||||||
|
const getState = jest.mocked(reduxStore.getState);
|
||||||
|
|
||||||
jest.mock('actions/views/rhs', () => ({
|
jest.mock('actions/views/rhs', () => ({
|
||||||
closeMenu: jest.fn(),
|
closeMenu: jest.fn(),
|
||||||
closeRightHandSide: jest.fn(),
|
closeRightHandSide: jest.fn(),
|
||||||
@ -64,7 +66,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
|
|
||||||
await redirectUserToDefaultTeam();
|
await redirectUserToDefaultTeam();
|
||||||
expect(getHistory().push).toHaveBeenCalledWith('/select_team');
|
expect(getHistory().push).toHaveBeenCalledWith('/select_team');
|
||||||
@ -138,7 +140,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
|
|
||||||
await redirectUserToDefaultTeam();
|
await redirectUserToDefaultTeam();
|
||||||
expect(getHistory().push).toHaveBeenCalledWith('/team2/channels/channel-in-team-2');
|
expect(getHistory().push).toHaveBeenCalledWith('/team2/channels/channel-in-team-2');
|
||||||
@ -211,7 +213,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
|
|
||||||
await redirectUserToDefaultTeam();
|
await redirectUserToDefaultTeam();
|
||||||
expect(getHistory().push).toHaveBeenCalledWith('/team2/channels/channel-in-team-2');
|
expect(getHistory().push).toHaveBeenCalledWith('/team2/channels/channel-in-team-2');
|
||||||
@ -283,7 +285,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
|
|
||||||
await redirectUserToDefaultTeam();
|
await redirectUserToDefaultTeam();
|
||||||
expect(getHistory().push).toHaveBeenCalledWith('/select_team');
|
expect(getHistory().push).toHaveBeenCalledWith('/select_team');
|
||||||
@ -315,7 +317,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
|
|
||||||
await redirectUserToDefaultTeam();
|
await redirectUserToDefaultTeam();
|
||||||
expect(getHistory().push).not.toHaveBeenCalled();
|
expect(getHistory().push).not.toHaveBeenCalled();
|
||||||
@ -408,7 +410,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
LocalStorageStore.setPreviousTeamId(userId, teamId);
|
LocalStorageStore.setPreviousTeamId(userId, teamId);
|
||||||
LocalStorageStore.setPreviousChannelName(userId, teamId, directChannelId);
|
LocalStorageStore.setPreviousChannelName(userId, teamId, directChannelId);
|
||||||
|
|
||||||
@ -505,7 +507,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
LocalStorageStore.setPreviousTeamId(userId, teamId);
|
LocalStorageStore.setPreviousTeamId(userId, teamId);
|
||||||
LocalStorageStore.setPreviousChannelName(userId, teamId, groupChannelId);
|
LocalStorageStore.setPreviousChannelName(userId, teamId, groupChannelId);
|
||||||
|
|
||||||
@ -567,7 +569,7 @@ describe('actions/global_actions', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
reduxStore.getState.mockImplementation(store.getState);
|
getState.mockImplementation(store.getState);
|
||||||
|
|
||||||
await redirectUserToDefaultTeam();
|
await redirectUserToDefaultTeam();
|
||||||
expect(getHistory().push).toHaveBeenCalledWith('/team1/channels/channel-in-team-1');
|
expect(getHistory().push).toHaveBeenCalledWith('/team1/channels/channel-in-team-1');
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import type {Dispatch, AnyAction} from 'redux';
|
||||||
|
|
||||||
import type {Channel, ChannelMembership, ChannelMessageCount} from '@mattermost/types/channels';
|
import type {Channel, ChannelMembership, ChannelMessageCount} from '@mattermost/types/channels';
|
||||||
import type {Post} from '@mattermost/types/posts';
|
import type {Post} from '@mattermost/types/posts';
|
||||||
import type {Team, TeamMembership} from '@mattermost/types/teams';
|
import type {Team, TeamMembership} from '@mattermost/types/teams';
|
||||||
@ -601,8 +603,8 @@ describe('Actions.User', () => {
|
|||||||
} as unknown as GlobalState;
|
} as unknown as GlobalState;
|
||||||
|
|
||||||
const testStore = mockStore(state);
|
const testStore = mockStore(state);
|
||||||
store.getState.mockImplementation(testStore.getState);
|
(store.getState as jest.MockedFunction<() => GlobalState>).mockImplementation(testStore.getState);
|
||||||
store.dispatch.mockImplementation(testStore.dispatch);
|
(store.dispatch as jest.MockedFunction<Dispatch<AnyAction>>).mockImplementation(testStore.dispatch);
|
||||||
const actions = testStore.getActions();
|
const actions = testStore.getActions();
|
||||||
|
|
||||||
await UserActions.loadProfilesForGM();
|
await UserActions.loadProfilesForGM();
|
||||||
|
@ -8,7 +8,7 @@ import {TestHelper} from 'utils/test_helper';
|
|||||||
|
|
||||||
import SearchChannelWithPermissionsProvider from './search_channel_with_permissions_provider';
|
import SearchChannelWithPermissionsProvider from './search_channel_with_permissions_provider';
|
||||||
|
|
||||||
const getState = store.getState;
|
const getState = jest.mocked(store.getState);
|
||||||
|
|
||||||
jest.mock('stores/redux_store', () => ({
|
jest.mock('stores/redux_store', () => ({
|
||||||
dispatch: jest.fn(),
|
dispatch: jest.fn(),
|
||||||
|
@ -133,6 +133,7 @@ const state: GlobalState = {
|
|||||||
commands: {},
|
commands: {},
|
||||||
appsBotIDs: [],
|
appsBotIDs: [],
|
||||||
appsOAuthAppIDs: [],
|
appsOAuthAppIDs: [],
|
||||||
|
dialogTriggerId: '',
|
||||||
outgoingOAuthConnections: {},
|
outgoingOAuthConnections: {},
|
||||||
},
|
},
|
||||||
files: {
|
files: {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import regeneratorRuntime from 'regenerator-runtime';
|
import regeneratorRuntime from 'regenerator-runtime';
|
||||||
|
|
||||||
import type {PluginManifest} from '@mattermost/types/plugins';
|
import type {PluginManifest, ClientPluginManifest} from '@mattermost/types/plugins';
|
||||||
|
|
||||||
import {Client4} from 'mattermost-redux/client';
|
import {Client4} from 'mattermost-redux/client';
|
||||||
import {Preferences} from 'mattermost-redux/constants';
|
import {Preferences} from 'mattermost-redux/constants';
|
||||||
@ -102,8 +102,8 @@ export async function initializePlugins(): Promise<void> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(data.map((m: PluginManifest) => {
|
await Promise.all(data.map(async (m: ClientPluginManifest) => {
|
||||||
return loadPlugin(m).catch((loadErr: Error) => {
|
return loadPlugin(m as PluginManifest).catch((loadErr: Error) => {
|
||||||
console.error(loadErr.message); //eslint-disable-line no-console
|
console.error(loadErr.message); //eslint-disable-line no-console
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@ -112,7 +112,7 @@ export async function initializePlugins(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getPlugins queries the server for all enabled plugins
|
// getPlugins queries the server for all enabled plugins
|
||||||
export function getPlugins(): ActionFuncAsync {
|
export function getPlugins(): ActionFuncAsync<ClientPluginManifest[]> {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
let plugins;
|
let plugins;
|
||||||
try {
|
try {
|
||||||
|
@ -34,8 +34,8 @@ store.subscribe(() => {
|
|||||||
|
|
||||||
previousTriggerId = currentTriggerId;
|
previousTriggerId = currentTriggerId;
|
||||||
|
|
||||||
const dialog = state.entities.integrations.dialog || {};
|
const dialog = state.entities.integrations.dialog;
|
||||||
if (dialog.trigger_id !== currentTriggerId) {
|
if (!dialog || dialog.trigger_id !== currentTriggerId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import type {GlobalState} from '@mattermost/types/store';
|
|
||||||
|
|
||||||
import {getCurrentTeamId, getTeamByName} from 'mattermost-redux/selectors/entities/teams';
|
import {getCurrentTeamId, getTeamByName} from 'mattermost-redux/selectors/entities/teams';
|
||||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||||
|
|
||||||
import localStorageStore from 'stores/local_storage_store';
|
import localStorageStore from 'stores/local_storage_store';
|
||||||
|
|
||||||
|
import type {GlobalState} from 'types/store';
|
||||||
|
|
||||||
// getLastViewedChannelName combines data from the Redux store and localStorage to return the
|
// getLastViewedChannelName combines data from the Redux store and localStorage to return the
|
||||||
// previously selected channel name, returning the default channel if none exists.
|
// previously selected channel name, returning the default channel if none exists.
|
||||||
//
|
//
|
||||||
|
@ -3,9 +3,13 @@
|
|||||||
|
|
||||||
import baseLocalForage from 'localforage';
|
import baseLocalForage from 'localforage';
|
||||||
import {extendPrototype} from 'localforage-observable';
|
import {extendPrototype} from 'localforage-observable';
|
||||||
|
import type {Store} from 'redux';
|
||||||
|
import type {Persistor} from 'redux-persist';
|
||||||
import {persistStore, REHYDRATE} from 'redux-persist';
|
import {persistStore, REHYDRATE} from 'redux-persist';
|
||||||
import Observable from 'zen-observable';
|
import Observable from 'zen-observable';
|
||||||
|
|
||||||
|
import type {DeepPartial} from '@mattermost/types/utilities';
|
||||||
|
|
||||||
import {General, RequestStatus} from 'mattermost-redux/constants';
|
import {General, RequestStatus} from 'mattermost-redux/constants';
|
||||||
import configureServiceStore from 'mattermost-redux/store';
|
import configureServiceStore from 'mattermost-redux/store';
|
||||||
|
|
||||||
@ -14,15 +18,23 @@ import {clearUserCookie} from 'actions/views/cookie';
|
|||||||
import appReducers from 'reducers';
|
import appReducers from 'reducers';
|
||||||
import {getBasePath} from 'selectors/general';
|
import {getBasePath} from 'selectors/general';
|
||||||
|
|
||||||
|
import type {GlobalState} from 'types/store';
|
||||||
|
|
||||||
function getAppReducers() {
|
function getAppReducers() {
|
||||||
return require('../reducers'); // eslint-disable-line global-require
|
return require('../reducers'); // eslint-disable-line global-require
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
Observable: typeof Observable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.Observable = Observable;
|
window.Observable = Observable;
|
||||||
|
|
||||||
const localForage = extendPrototype(baseLocalForage);
|
const localForage = extendPrototype(baseLocalForage);
|
||||||
|
|
||||||
export default function configureStore(preloadedState, additionalReducers) {
|
export default function configureStore(preloadedState?: DeepPartial<GlobalState>, additionalReducers?: Record<string, any>): Store<GlobalState> {
|
||||||
const reducers = additionalReducers ? {...appReducers, ...additionalReducers} : appReducers;
|
const reducers = additionalReducers ? {...appReducers, ...additionalReducers} : appReducers;
|
||||||
const store = configureServiceStore({
|
const store = configureServiceStore({
|
||||||
appReducers: reducers,
|
appReducers: reducers,
|
||||||
@ -31,7 +43,7 @@ export default function configureStore(preloadedState, additionalReducers) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
localForage.ready().then(() => {
|
localForage.ready().then(() => {
|
||||||
const persistor = persistStore(store, null, () => {
|
const persistor: Persistor = persistStore(store, null, () => {
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: General.STORE_REHYDRATION_COMPLETE,
|
type: General.STORE_REHYDRATION_COMPLETE,
|
||||||
complete: true,
|
complete: true,
|
||||||
@ -51,23 +63,23 @@ export default function configureStore(preloadedState, additionalReducers) {
|
|||||||
|
|
||||||
// Rehydrate redux-persist when another tab changes localForage
|
// Rehydrate redux-persist when another tab changes localForage
|
||||||
observable.subscribe({
|
observable.subscribe({
|
||||||
next: (args) => {
|
next: (value) => {
|
||||||
if (!args.crossTabNotification) {
|
if (!value.crossTabNotification) {
|
||||||
// Ignore changes made by this tab
|
// Ignore changes made by this tab
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyPrefix = 'persist:';
|
const keyPrefix = 'persist:';
|
||||||
|
|
||||||
if (!args.key.startsWith(keyPrefix)) {
|
if (!value.key.startsWith(keyPrefix)) {
|
||||||
// Ignore changes that weren't made by redux-persist
|
// Ignore changes that weren't made by redux-persist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = args.key.substring(keyPrefix.length);
|
const key = value.key.substring(keyPrefix.length);
|
||||||
const newValue = JSON.parse(args.newValue);
|
const newValue = JSON.parse(value.newValue);
|
||||||
|
|
||||||
const payload = {};
|
const payload: Record<string, any> = {};
|
||||||
|
|
||||||
for (const reducerKey of Object.keys(newValue)) {
|
for (const reducerKey of Object.keys(newValue)) {
|
||||||
if (reducerKey === '_persist') {
|
if (reducerKey === '_persist') {
|
||||||
@ -110,7 +122,7 @@ export default function configureStore(preloadedState, additionalReducers) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).catch((e) => {
|
}).catch((e: Error) => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error('Failed to initialize localForage', e);
|
console.error('Failed to initialize localForage', e);
|
||||||
});
|
});
|
||||||
@ -121,11 +133,11 @@ export default function configureStore(preloadedState, additionalReducers) {
|
|||||||
/**
|
/**
|
||||||
* Migrates state.storage from redux-persist@4 to redux-persist@6
|
* Migrates state.storage from redux-persist@4 to redux-persist@6
|
||||||
*/
|
*/
|
||||||
function migratePersistedState(store, persistor) {
|
function migratePersistedState(store: Store<GlobalState>, persistor: Persistor): void {
|
||||||
const oldKeyPrefix = 'reduxPersist:storage:';
|
const oldKeyPrefix = 'reduxPersist:storage:';
|
||||||
|
|
||||||
const restoredState = {};
|
const restoredState: Record<string, string> = {};
|
||||||
localForage.iterate((value, key) => {
|
localForage.iterate((value: string, key: string) => {
|
||||||
if (key && key.startsWith(oldKeyPrefix)) {
|
if (key && key.startsWith(oldKeyPrefix)) {
|
||||||
restoredState[key.substring(oldKeyPrefix.length)] = value;
|
restoredState[key.substring(oldKeyPrefix.length)] = value;
|
||||||
}
|
}
|
||||||
@ -140,7 +152,7 @@ function migratePersistedState(store, persistor) {
|
|||||||
|
|
||||||
persistor.pause();
|
persistor.pause();
|
||||||
|
|
||||||
const persistedState = {};
|
const persistedState: Record<string, any> = {};
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(restoredState)) {
|
for (const [key, value] of Object.entries(restoredState)) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
@ -91,12 +91,12 @@ class LocalStorageStoreClass {
|
|||||||
this.removeItem(getPenultimateChannelNameKey(userId, teamId));
|
this.removeItem(getPenultimateChannelNameKey(userId, teamId));
|
||||||
}
|
}
|
||||||
|
|
||||||
removePreviousChannelType(userId: string, teamId: string, state = store.getStore()) {
|
removePreviousChannelType(userId: string, teamId: string, state = store.getState()) {
|
||||||
this.setItem(getPreviousViewedTypeKey(userId, teamId), this.getPenultimateViewedType(userId, teamId, state));
|
this.setItem(getPreviousViewedTypeKey(userId, teamId), this.getPenultimateViewedType(userId, teamId, state));
|
||||||
this.removeItem(getPenultimateViewedTypeKey(userId, teamId));
|
this.removeItem(getPenultimateViewedTypeKey(userId, teamId));
|
||||||
}
|
}
|
||||||
|
|
||||||
removePreviousChannel(userId: string, teamId: string, state = store.getStore()) {
|
removePreviousChannel(userId: string, teamId: string, state = store.getState()) {
|
||||||
this.removePreviousChannelName(userId, teamId, state);
|
this.removePreviousChannelName(userId, teamId, state);
|
||||||
this.removePreviousChannelType(userId, teamId, state);
|
this.removePreviousChannelType(userId, teamId, state);
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ function replaceGlobalStore(getStore: () => any) {
|
|||||||
jest.spyOn(globalStore, 'dispatch').mockImplementation((...args) => getStore().dispatch(...args));
|
jest.spyOn(globalStore, 'dispatch').mockImplementation((...args) => getStore().dispatch(...args));
|
||||||
jest.spyOn(globalStore, 'getState').mockImplementation(() => getStore().getState());
|
jest.spyOn(globalStore, 'getState').mockImplementation(() => getStore().getState());
|
||||||
jest.spyOn(globalStore, 'replaceReducer').mockImplementation((...args) => getStore().replaceReducer(...args));
|
jest.spyOn(globalStore, 'replaceReducer').mockImplementation((...args) => getStore().replaceReducer(...args));
|
||||||
jest.spyOn(globalStore, '@@observable').mockImplementation((...args) => getStore()['@@observable'](...args));
|
jest.spyOn(globalStore, '@@observable' as any).mockImplementation((...args: any[]) => getStore()['@@observable'](...args));
|
||||||
|
|
||||||
// This may stop working if getStore starts to return new results
|
// This may stop working if getStore starts to return new results
|
||||||
jest.spyOn(globalStore, 'subscribe').mockImplementation((...args) => getStore().subscribe(...args));
|
jest.spyOn(globalStore, 'subscribe').mockImplementation((...args) => getStore().subscribe(...args));
|
||||||
|
@ -172,7 +172,7 @@ describe('Utils.localizeMessage', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
} as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('with translations', () => {
|
test('with translations', () => {
|
||||||
@ -200,7 +200,7 @@ describe('Utils.localizeMessage', () => {
|
|||||||
translations: {},
|
translations: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
} as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('without translations', () => {
|
test('without translations', () => {
|
||||||
|
@ -1286,7 +1286,7 @@ export async function handleFormattedTextClick(e: React.MouseEvent, currentRelat
|
|||||||
let post = getPost(state, postId!);
|
let post = getPost(state, postId!);
|
||||||
if (!post) {
|
if (!post) {
|
||||||
const {data: postData} = await store.dispatch(getPostAction(match.postId!));
|
const {data: postData} = await store.dispatch(getPostAction(match.postId!));
|
||||||
post = postData;
|
post = postData!;
|
||||||
}
|
}
|
||||||
if (post) {
|
if (post) {
|
||||||
isReply = Boolean(post.root_id);
|
isReply = Boolean(post.root_id);
|
||||||
@ -1303,12 +1303,12 @@ export async function handleFormattedTextClick(e: React.MouseEvent, currentRelat
|
|||||||
if (!member) {
|
if (!member) {
|
||||||
const membership = await store.dispatch(getChannelMember(channel.id, getCurrentUserId(state)));
|
const membership = await store.dispatch(getChannelMember(channel.id, getCurrentUserId(state)));
|
||||||
if ('data' in membership) {
|
if ('data' in membership) {
|
||||||
member = membership.data;
|
member = membership.data!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!member) {
|
if (!member) {
|
||||||
const {data} = await store.dispatch(joinPrivateChannelPrompt(team, channel.display_name, false));
|
const {data} = await store.dispatch(joinPrivateChannelPrompt(team, channel.display_name, false));
|
||||||
if (data.join) {
|
if (data!.join) {
|
||||||
let error = false;
|
let error = false;
|
||||||
if (!getTeamMemberships(state)[team.id]) {
|
if (!getTeamMemberships(state)[team.id]) {
|
||||||
const joinTeamResult = await store.dispatch(addUserToTeam(team.id, user.id));
|
const joinTeamResult = await store.dispatch(addUserToTeam(team.id, user.id));
|
||||||
|
7
webapp/package-lock.json
generated
7
webapp/package-lock.json
generated
@ -193,6 +193,7 @@
|
|||||||
"@types/shallow-equals": "1.0.3",
|
"@types/shallow-equals": "1.0.3",
|
||||||
"@types/styled-components": "5.1.32",
|
"@types/styled-components": "5.1.32",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
|
"@types/zen-observable": "0.8.7",
|
||||||
"copy-webpack-plugin": "11.0.0",
|
"copy-webpack-plugin": "11.0.0",
|
||||||
"emoji-datasource": "6.1.1",
|
"emoji-datasource": "6.1.1",
|
||||||
"emoji-datasource-apple": "6.1.1",
|
"emoji-datasource-apple": "6.1.1",
|
||||||
@ -7310,6 +7311,12 @@
|
|||||||
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
|
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/zen-observable": {
|
||||||
|
"version": "0.8.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.7.tgz",
|
||||||
|
"integrity": "sha512-LKzNTjj+2j09wAo/vvVjzgw5qckJJzhdGgWHW7j69QIGdq/KnZrMAMIHQiWGl3Ccflh5/CudBAntTPYdprPltA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "7.18.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz",
|
||||||
|
@ -134,9 +134,11 @@ export type IntegrationsState = {
|
|||||||
appsBotIDs: string[];
|
appsBotIDs: string[];
|
||||||
systemCommands: IDMappedObjects<Command>;
|
systemCommands: IDMappedObjects<Command>;
|
||||||
commands: IDMappedObjects<Command>;
|
commands: IDMappedObjects<Command>;
|
||||||
|
dialogTriggerId: string;
|
||||||
dialog?: {
|
dialog?: {
|
||||||
url: string;
|
url: string;
|
||||||
dialog: Dialog;
|
dialog: Dialog;
|
||||||
|
trigger_id: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user