[MM-48670] Fix persistence of placeholder text (#22820)
Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
b200a07881
Коммит
0c375e1ebd
@@ -18,7 +18,7 @@ import {
|
|||||||
makeOnSubmit,
|
makeOnSubmit,
|
||||||
makeOnEditLatestPost,
|
makeOnEditLatestPost,
|
||||||
} from 'actions/views/create_comment';
|
} from 'actions/views/create_comment';
|
||||||
import {removeDraft} from 'actions/views/drafts';
|
import {removeDraft, setGlobalDraftSource} from 'actions/views/drafts';
|
||||||
import {setGlobalItem, actionOnGlobalItemsWithPrefix} from 'actions/storage';
|
import {setGlobalItem, actionOnGlobalItemsWithPrefix} from 'actions/storage';
|
||||||
import * as PostActions from 'actions/post_actions';
|
import * as PostActions from 'actions/post_actions';
|
||||||
import {executeCommand} from 'actions/command';
|
import {executeCommand} from 'actions/command';
|
||||||
@@ -205,12 +205,13 @@ describe('rhs view actions', () => {
|
|||||||
|
|
||||||
const testStore = mockStore(initialState);
|
const testStore = mockStore(initialState);
|
||||||
|
|
||||||
testStore.dispatch(setGlobalItem(`${StoragePrefixes.COMMENT_DRAFT}${rootId}`, {
|
const expectedKey = `${StoragePrefixes.COMMENT_DRAFT}${rootId}`;
|
||||||
|
testStore.dispatch(setGlobalItem(expectedKey, {
|
||||||
...draft,
|
...draft,
|
||||||
createAt: 42,
|
createAt: 42,
|
||||||
updateAt: 42,
|
updateAt: 42,
|
||||||
remote: false,
|
|
||||||
}));
|
}));
|
||||||
|
testStore.dispatch(setGlobalDraftSource(expectedKey, false));
|
||||||
|
|
||||||
expect(store.getActions()).toEqual(testStore.getActions());
|
expect(store.getActions()).toEqual(testStore.getActions());
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils';
|
|||||||
|
|
||||||
import {Client4} from 'mattermost-redux/client';
|
import {Client4} from 'mattermost-redux/client';
|
||||||
|
|
||||||
import {removeDraft, updateDraft} from './drafts';
|
import {removeDraft, setGlobalDraftSource, updateDraft} from './drafts';
|
||||||
|
|
||||||
jest.mock('mattermost-redux/client', () => {
|
jest.mock('mattermost-redux/client', () => {
|
||||||
const original = jest.requireActual('mattermost-redux/client');
|
const original = jest.requireActual('mattermost-redux/client');
|
||||||
@@ -146,12 +146,13 @@ describe('draft actions', () => {
|
|||||||
|
|
||||||
const testStore = mockStore(initialState);
|
const testStore = mockStore(initialState);
|
||||||
|
|
||||||
testStore.dispatch(setGlobalItem(StoragePrefixes.DRAFT + channelId, {
|
const expectedKey = StoragePrefixes.DRAFT + channelId;
|
||||||
|
testStore.dispatch(setGlobalItem(expectedKey, {
|
||||||
...draft,
|
...draft,
|
||||||
createAt: 42,
|
createAt: 42,
|
||||||
updateAt: 42,
|
updateAt: 42,
|
||||||
remote: false,
|
|
||||||
}));
|
}));
|
||||||
|
testStore.dispatch(setGlobalDraftSource(expectedKey, false));
|
||||||
|
|
||||||
expect(store.getActions()).toEqual(testStore.getActions());
|
expect(store.getActions()).toEqual(testStore.getActions());
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {PostDraft} from 'types/store/draft';
|
|||||||
import {getGlobalItem} from 'selectors/storage';
|
import {getGlobalItem} from 'selectors/storage';
|
||||||
import {makeGetDrafts} from 'selectors/drafts';
|
import {makeGetDrafts} from 'selectors/drafts';
|
||||||
|
|
||||||
import {StoragePrefixes} from 'utils/constants';
|
import {ActionTypes, StoragePrefixes} from 'utils/constants';
|
||||||
|
|
||||||
import type {Draft as ServerDraft} from '@mattermost/types/drafts';
|
import type {Draft as ServerDraft} from '@mattermost/types/drafts';
|
||||||
import type {UserProfile} from '@mattermost/types/users';
|
import type {UserProfile} from '@mattermost/types/users';
|
||||||
@@ -101,11 +101,10 @@ export function updateDraft(key: string, value: PostDraft|null, rootId = '', sav
|
|||||||
...value,
|
...value,
|
||||||
createAt: data.createAt || timestamp,
|
createAt: data.createAt || timestamp,
|
||||||
updateAt: timestamp,
|
updateAt: timestamp,
|
||||||
remote: false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(setGlobalItem(key, updatedValue));
|
dispatch(setGlobalDraft(key, updatedValue, false));
|
||||||
|
|
||||||
if (syncedDraftsAreAllowedAndEnabled(state) && save && updatedValue) {
|
if (syncedDraftsAreAllowedAndEnabled(state) && save && updatedValue) {
|
||||||
const connectionId = getConnectionId(state);
|
const connectionId = getConnectionId(state);
|
||||||
@@ -153,6 +152,24 @@ export function setDraftsTourTipPreference(initializationState: Record<string, b
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setGlobalDraft(key: string, value: PostDraft|null, isRemote: boolean) {
|
||||||
|
return (dispatch: DispatchFunc) => {
|
||||||
|
dispatch(setGlobalItem(key, value));
|
||||||
|
dispatch(setGlobalDraftSource(key, isRemote));
|
||||||
|
return {data: true};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setGlobalDraftSource(key: string, isRemote: boolean) {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.SET_DRAFT_SOURCE,
|
||||||
|
data: {
|
||||||
|
key,
|
||||||
|
isRemote,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function transformServerDraft(draft: ServerDraft): Draft {
|
export function transformServerDraft(draft: ServerDraft): Draft {
|
||||||
let key: Draft['key'] = `${StoragePrefixes.DRAFT}${draft.channel_id}`;
|
let key: Draft['key'] = `${StoragePrefixes.DRAFT}${draft.channel_id}`;
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ import {
|
|||||||
} from 'mattermost-redux/actions/users';
|
} from 'mattermost-redux/actions/users';
|
||||||
import {removeNotVisibleUsers} from 'mattermost-redux/actions/websocket';
|
import {removeNotVisibleUsers} from 'mattermost-redux/actions/websocket';
|
||||||
import {setGlobalItem} from 'actions/storage';
|
import {setGlobalItem} from 'actions/storage';
|
||||||
import {transformServerDraft} from 'actions/views/drafts';
|
import {setGlobalDraft, transformServerDraft} from 'actions/views/drafts';
|
||||||
|
|
||||||
import {Client4} from 'mattermost-redux/client';
|
import {Client4} from 'mattermost-redux/client';
|
||||||
import {getCurrentUser, getCurrentUserId, getUser, getIsManualStatusForUserId, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
import {getCurrentUser, getCurrentUserId, getUser, getIsManualStatusForUserId, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||||
@@ -89,7 +89,6 @@ import {getStandardAnalytics} from 'mattermost-redux/actions/admin';
|
|||||||
|
|
||||||
import {fetchAppBindings, fetchRHSAppsBindings} from 'mattermost-redux/actions/apps';
|
import {fetchAppBindings, fetchRHSAppsBindings} from 'mattermost-redux/actions/apps';
|
||||||
|
|
||||||
import {getConnectionId} from 'selectors/general';
|
|
||||||
import {getSelectedChannelId, getSelectedPost} from 'selectors/rhs';
|
import {getSelectedChannelId, getSelectedPost} from 'selectors/rhs';
|
||||||
import {isThreadOpen, isThreadManuallyUnread} from 'selectors/views/threads';
|
import {isThreadOpen, isThreadManuallyUnread} from 'selectors/views/threads';
|
||||||
|
|
||||||
@@ -1700,20 +1699,12 @@ function handlePostAcknowledgementRemoved(msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleUpsertDraftEvent(msg) {
|
function handleUpsertDraftEvent(msg) {
|
||||||
return async (doDispatch, doGetState) => {
|
return async (doDispatch) => {
|
||||||
const state = doGetState();
|
|
||||||
const connectionId = getConnectionId(state);
|
|
||||||
|
|
||||||
const draft = JSON.parse(msg.data.draft);
|
const draft = JSON.parse(msg.data.draft);
|
||||||
const {key, value} = transformServerDraft(draft);
|
const {key, value} = transformServerDraft(draft);
|
||||||
value.show = true;
|
value.show = true;
|
||||||
value.remote = false;
|
|
||||||
|
|
||||||
if (msg.broadcast.omit_connection_id !== connectionId) {
|
doDispatch(setGlobalDraft(key, value, true));
|
||||||
value.remote = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
doDispatch(setGlobalItem(key, value));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1722,7 +1713,11 @@ function handleDeleteDraftEvent(msg) {
|
|||||||
const draft = JSON.parse(msg.data.draft);
|
const draft = JSON.parse(msg.data.draft);
|
||||||
const {key} = transformServerDraft(draft);
|
const {key} = transformServerDraft(draft);
|
||||||
|
|
||||||
doDispatch(setGlobalItem(key, {message: '', fileInfos: [], uploadsInProgress: [], remote: true}));
|
doDispatch(setGlobalItem(key, {
|
||||||
|
message: '',
|
||||||
|
fileInfos: [],
|
||||||
|
uploadsInProgress: [],
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ describe('components/AdvancedCreateComment', () => {
|
|||||||
uploadsInProgress: [{}],
|
uploadsInProgress: [{}],
|
||||||
fileInfos: [{}, {}, {}],
|
fileInfos: [{}, {}, {}],
|
||||||
},
|
},
|
||||||
|
isRemoteDraft: false,
|
||||||
enableAddButton: true,
|
enableAddButton: true,
|
||||||
ctrlSend: false,
|
ctrlSend: false,
|
||||||
latestPostId,
|
latestPostId,
|
||||||
@@ -84,9 +85,10 @@ describe('components/AdvancedCreateComment', () => {
|
|||||||
|
|
||||||
test('should match snapshot, empty comment', () => {
|
test('should match snapshot, empty comment', () => {
|
||||||
const draft = emptyDraft;
|
const draft = emptyDraft;
|
||||||
|
const isRemoteDraft = false;
|
||||||
const enableAddButton = false;
|
const enableAddButton = false;
|
||||||
const ctrlSend = true;
|
const ctrlSend = true;
|
||||||
const props = {...baseProps, draft, enableAddButton, ctrlSend};
|
const props = {...baseProps, draft, isRemoteDraft, enableAddButton, ctrlSend};
|
||||||
|
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<AdvancedCreateComment {...props}/>,
|
<AdvancedCreateComment {...props}/>,
|
||||||
@@ -104,8 +106,9 @@ describe('components/AdvancedCreateComment', () => {
|
|||||||
uploadsInProgress: [],
|
uploadsInProgress: [],
|
||||||
fileInfos: [],
|
fileInfos: [],
|
||||||
};
|
};
|
||||||
|
const isRemoteDraft = false;
|
||||||
const ctrlSend = true;
|
const ctrlSend = true;
|
||||||
const props = {...baseProps, ctrlSend, draft, clearCommentDraftUploads, onResetHistoryIndex, getChannelMemberCountsByGroup};
|
const props = {...baseProps, ctrlSend, draft, isRemoteDraft, clearCommentDraftUploads, onResetHistoryIndex, getChannelMemberCountsByGroup};
|
||||||
|
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<AdvancedCreateComment {...props}/>,
|
<AdvancedCreateComment {...props}/>,
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ type Props = {
|
|||||||
// The current draft of the comment
|
// The current draft of the comment
|
||||||
draft: PostDraft;
|
draft: PostDraft;
|
||||||
|
|
||||||
|
// Data used for knowing if the draft came from a WS event
|
||||||
|
isRemoteDraft: boolean;
|
||||||
|
|
||||||
// Determines if the submit button should be rendered
|
// Determines if the submit button should be rendered
|
||||||
enableAddButton?: boolean;
|
enableAddButton?: boolean;
|
||||||
|
|
||||||
@@ -233,8 +236,14 @@ class AdvancedCreateComment extends React.PureComponent<Props, State> {
|
|||||||
|
|
||||||
const rootChanged = props.rootId !== state.rootId;
|
const rootChanged = props.rootId !== state.rootId;
|
||||||
const messageInHistoryChanged = props.messageInHistory !== state.messageInHistory;
|
const messageInHistoryChanged = props.messageInHistory !== state.messageInHistory;
|
||||||
if (rootChanged || messageInHistoryChanged || props.draft.remote) {
|
if (rootChanged || messageInHistoryChanged || (props.isRemoteDraft && props.draft.message !== state.draft?.message)) {
|
||||||
updatedState = {...updatedState, draft: {...props.draft, uploadsInProgress: rootChanged ? [] : props.draft.uploadsInProgress}};
|
updatedState = {
|
||||||
|
...updatedState,
|
||||||
|
draft: {
|
||||||
|
...props.draft,
|
||||||
|
uploadsInProgress: rootChanged ? [] : props.draft.uploadsInProgress,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatedState;
|
return updatedState;
|
||||||
@@ -252,6 +261,7 @@ class AdvancedCreateComment extends React.PureComponent<Props, State> {
|
|||||||
serverError: null,
|
serverError: null,
|
||||||
showFormat: false,
|
showFormat: false,
|
||||||
isFormattingBarHidden: props.isFormattingBarHidden,
|
isFormattingBarHidden: props.isFormattingBarHidden,
|
||||||
|
caretPosition: props.draft.caretPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.textboxRef = React.createRef();
|
this.textboxRef = React.createRef();
|
||||||
@@ -343,7 +353,6 @@ class AdvancedCreateComment extends React.PureComponent<Props, State> {
|
|||||||
const updatedDraft = {
|
const updatedDraft = {
|
||||||
...this.state.draft,
|
...this.state.draft,
|
||||||
show: !isDraftEmpty(this.state.draft),
|
show: !isDraftEmpty(this.state.draft),
|
||||||
remote: false,
|
|
||||||
} as PostDraft;
|
} as PostDraft;
|
||||||
|
|
||||||
this.props.onUpdateCommentDraft(updatedDraft, true);
|
this.props.onUpdateCommentDraft(updatedDraft, true);
|
||||||
@@ -356,7 +365,6 @@ class AdvancedCreateComment extends React.PureComponent<Props, State> {
|
|||||||
draft: {
|
draft: {
|
||||||
...prev.draft,
|
...prev.draft,
|
||||||
show: !isDraftEmpty(prev.draft),
|
show: !isDraftEmpty(prev.draft),
|
||||||
remote: false,
|
|
||||||
} as PostDraft,
|
} as PostDraft,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ function makeMapStateToProps() {
|
|||||||
const err = state.requests.posts.createPost.error || {};
|
const err = state.requests.posts.createPost.error || {};
|
||||||
|
|
||||||
const draft = getPostDraft(state, StoragePrefixes.COMMENT_DRAFT, ownProps.rootId);
|
const draft = getPostDraft(state, StoragePrefixes.COMMENT_DRAFT, ownProps.rootId);
|
||||||
|
const isRemoteDraft = state.views.drafts.remotes[`${StoragePrefixes.COMMENT_DRAFT}${ownProps.rootId}`] || false;
|
||||||
|
|
||||||
const channelMembersCount = getAllChannelStats(state)[ownProps.channelId] ? getAllChannelStats(state)[ownProps.channelId].member_count : 1;
|
const channelMembersCount = getAllChannelStats(state)[ownProps.channelId] ? getAllChannelStats(state)[ownProps.channelId].member_count : 1;
|
||||||
const messageInHistory = getMessageInHistoryItem(state);
|
const messageInHistory = getMessageInHistoryItem(state);
|
||||||
@@ -91,6 +92,7 @@ function makeMapStateToProps() {
|
|||||||
return {
|
return {
|
||||||
currentTeamId,
|
currentTeamId,
|
||||||
draft,
|
draft,
|
||||||
|
isRemoteDraft,
|
||||||
messageInHistory,
|
messageInHistory,
|
||||||
channelMembersCount,
|
channelMembersCount,
|
||||||
currentUserId,
|
currentUserId,
|
||||||
@@ -121,11 +123,11 @@ function makeMapStateToProps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function makeOnUpdateCommentDraft(rootId: string, channelId: string) {
|
function makeOnUpdateCommentDraft(rootId: string, channelId: string) {
|
||||||
return (draft?: PostDraft, save = false) => updateCommentDraft(rootId, draft ? {...draft, channelId, remote: false} : draft, save);
|
return (draft?: PostDraft, save = false) => updateCommentDraft(rootId, draft ? {...draft, channelId} : draft, save);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeUpdateCommentDraftWithRootId(channelId: string) {
|
function makeUpdateCommentDraftWithRootId(channelId: string) {
|
||||||
return (rootId: string, draft?: PostDraft, save = false) => updateCommentDraft(rootId, draft ? {...draft, channelId, remote: false} : draft, save);
|
return (rootId: string, draft?: PostDraft, save = false) => updateCommentDraft(rootId, draft ? {...draft, channelId} : draft, save);
|
||||||
}
|
}
|
||||||
|
|
||||||
type Actions = {
|
type Actions = {
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ function advancedCreatePost({
|
|||||||
fullWidthTextBox={fullWidthTextBox}
|
fullWidthTextBox={fullWidthTextBox}
|
||||||
currentChannelMembersCount={currentChannelMembersCount}
|
currentChannelMembersCount={currentChannelMembersCount}
|
||||||
draft={draft}
|
draft={draft}
|
||||||
|
isRemoteDraft={false}
|
||||||
recentPostIdInChannel={recentPostIdInChannel}
|
recentPostIdInChannel={recentPostIdInChannel}
|
||||||
latestReplyablePostId={latestReplyablePostId}
|
latestReplyablePostId={latestReplyablePostId}
|
||||||
locale={locale}
|
locale={locale}
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ type Props = {
|
|||||||
// Data used for populating message state from previous draft
|
// Data used for populating message state from previous draft
|
||||||
draft: PostDraft;
|
draft: PostDraft;
|
||||||
|
|
||||||
|
// Data used for knowing if the draft came from a WS event
|
||||||
|
isRemoteDraft: boolean;
|
||||||
|
|
||||||
// Data used dispatching handleViewAction ex: edit post
|
// Data used dispatching handleViewAction ex: edit post
|
||||||
latestReplyablePostId?: string;
|
latestReplyablePostId?: string;
|
||||||
locale: string;
|
locale: string;
|
||||||
@@ -279,7 +282,7 @@ class AdvancedCreatePost extends React.PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
if (
|
if (
|
||||||
props.currentChannel.id !== state.currentChannel.id ||
|
props.currentChannel.id !== state.currentChannel.id ||
|
||||||
(props.draft.remote && props.draft.message !== state.message)
|
(props.isRemoteDraft && props.draft.message !== state.message)
|
||||||
) {
|
) {
|
||||||
updatedState = {
|
updatedState = {
|
||||||
...updatedState,
|
...updatedState,
|
||||||
@@ -294,8 +297,8 @@ class AdvancedCreatePost extends React.PureComponent<Props, State> {
|
|||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
message: this.props.draft.message,
|
message: props.draft.message,
|
||||||
caretPosition: this.props.draft.message.length,
|
caretPosition: props.draft.message.length,
|
||||||
submitting: false,
|
submitting: false,
|
||||||
showEmojiPicker: false,
|
showEmojiPicker: false,
|
||||||
uploadsProgressPercent: {},
|
uploadsProgressPercent: {},
|
||||||
@@ -387,7 +390,6 @@ class AdvancedCreatePost extends React.PureComponent<Props, State> {
|
|||||||
this.draftsForChannel[channelId] = {
|
this.draftsForChannel[channelId] = {
|
||||||
...draft,
|
...draft,
|
||||||
show: !isDraftEmpty(draft),
|
show: !isDraftEmpty(draft),
|
||||||
remote: false,
|
|
||||||
} as PostDraft;
|
} as PostDraft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ function makeMapStateToProps() {
|
|||||||
const currentChannel = getCurrentChannel(state) || {};
|
const currentChannel = getCurrentChannel(state) || {};
|
||||||
const currentChannelTeammateUsername = getUser(state, currentChannel.teammate_id || '')?.username;
|
const currentChannelTeammateUsername = getUser(state, currentChannel.teammate_id || '')?.username;
|
||||||
const draft = getChannelDraft(state, currentChannel.id);
|
const draft = getChannelDraft(state, currentChannel.id);
|
||||||
|
const isRemoteDraft = state.views.drafts.remotes[`${StoragePrefixes.DRAFT}${currentChannel.id}`] || false;
|
||||||
const latestReplyablePostId = getLatestReplyablePostId(state);
|
const latestReplyablePostId = getLatestReplyablePostId(state);
|
||||||
const currentChannelMembersCount = getCurrentChannelStats(state) ? getCurrentChannelStats(state).member_count : 1;
|
const currentChannelMembersCount = getCurrentChannelStats(state) ? getCurrentChannelStats(state).member_count : 1;
|
||||||
const enableEmojiPicker = config.EnableEmojiPicker === 'true';
|
const enableEmojiPicker = config.EnableEmojiPicker === 'true';
|
||||||
@@ -117,6 +118,7 @@ function makeMapStateToProps() {
|
|||||||
showSendTutorialTip,
|
showSendTutorialTip,
|
||||||
messageInHistoryItem: getMessageInHistoryItem(state),
|
messageInHistoryItem: getMessageInHistoryItem(state),
|
||||||
draft,
|
draft,
|
||||||
|
isRemoteDraft,
|
||||||
latestReplyablePostId,
|
latestReplyablePostId,
|
||||||
locale: getCurrentLocale(state),
|
locale: getCurrentLocale(state),
|
||||||
currentUsersLatestPost: getCurrentUsersLatestPost(state, ''),
|
currentUsersLatestPost: getCurrentUsersLatestPost(state, ''),
|
||||||
@@ -181,12 +183,7 @@ function setDraft(key: string, value: PostDraft, draftChannelId: string, save =
|
|||||||
const channelId = draftChannelId || getCurrentChannelId(getState());
|
const channelId = draftChannelId || getCurrentChannelId(getState());
|
||||||
let updatedValue = null;
|
let updatedValue = null;
|
||||||
if (value) {
|
if (value) {
|
||||||
updatedValue = {...value};
|
updatedValue = {...value, channelId};
|
||||||
updatedValue = {
|
|
||||||
...value,
|
|
||||||
channelId,
|
|
||||||
remote: false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (updatedValue) {
|
if (updatedValue) {
|
||||||
return dispatch(updateDraft(key, updatedValue, '', save));
|
return dispatch(updateDraft(key, updatedValue, '', save));
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ exports[`components/drafts/drafts_row should match snapshot for channel draft 1`
|
|||||||
"type": "channel",
|
"type": "channel",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isRemote={false}
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
user={Object {}}
|
user={Object {}}
|
||||||
/>
|
/>
|
||||||
@@ -84,6 +85,7 @@ exports[`components/drafts/drafts_row should match snapshot for thread draft 1`]
|
|||||||
"type": "thread",
|
"type": "thread",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isRemote={false}
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
user={Object {}}
|
user={Object {}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ exports[`components/drafts/drafts should match snapshot 1`] = `
|
|||||||
>
|
>
|
||||||
<Memo(Drafts)
|
<Memo(Drafts)
|
||||||
displayName="display_name"
|
displayName="display_name"
|
||||||
|
draftRemotes={Object {}}
|
||||||
drafts={Array []}
|
drafts={Array []}
|
||||||
localDraftsAreEnabled={true}
|
localDraftsAreEnabled={true}
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
@@ -76,6 +77,7 @@ exports[`components/drafts/drafts should match snapshot for local drafts disable
|
|||||||
>
|
>
|
||||||
<Memo(Drafts)
|
<Memo(Drafts)
|
||||||
displayName="display_name"
|
displayName="display_name"
|
||||||
|
draftRemotes={Object {}}
|
||||||
drafts={Array []}
|
drafts={Array []}
|
||||||
localDraftsAreEnabled={false}
|
localDraftsAreEnabled={false}
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ exports[`components/drafts/drafts_row should match snapshot for channel draft 1`
|
|||||||
displayName=""
|
displayName=""
|
||||||
draftId=""
|
draftId=""
|
||||||
id={Object {}}
|
id={Object {}}
|
||||||
|
isRemote={false}
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
type="channel"
|
type="channel"
|
||||||
user={Object {}}
|
user={Object {}}
|
||||||
@@ -88,6 +89,7 @@ exports[`components/drafts/drafts_row should match snapshot for undefined channe
|
|||||||
displayName=""
|
displayName=""
|
||||||
draftId=""
|
draftId=""
|
||||||
id={Object {}}
|
id={Object {}}
|
||||||
|
isRemote={false}
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
type="channel"
|
type="channel"
|
||||||
user={Object {}}
|
user={Object {}}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ describe('components/drafts/drafts_row', () => {
|
|||||||
type: 'channel' as 'channel' | 'thread',
|
type: 'channel' as 'channel' | 'thread',
|
||||||
user: {} as UserProfile,
|
user: {} as UserProfile,
|
||||||
value: {} as PostDraft,
|
value: {} as PostDraft,
|
||||||
|
isRemote: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should match snapshot for channel draft', () => {
|
it('should match snapshot for channel draft', () => {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ type Props = {
|
|||||||
type: 'channel' | 'thread';
|
type: 'channel' | 'thread';
|
||||||
user: UserProfile;
|
user: UserProfile;
|
||||||
value: PostDraft;
|
value: PostDraft;
|
||||||
|
isRemote: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ChannelDraft({
|
function ChannelDraft({
|
||||||
@@ -40,6 +41,7 @@ function ChannelDraft({
|
|||||||
type,
|
type,
|
||||||
user,
|
user,
|
||||||
value,
|
value,
|
||||||
|
isRemote,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -101,7 +103,7 @@ function ChannelDraft({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
timestamp={value.updateAt}
|
timestamp={value.updateAt}
|
||||||
remote={value.remote || false}
|
remote={isRemote || false}
|
||||||
/>
|
/>
|
||||||
<PanelBody
|
<PanelBody
|
||||||
channelId={channel.id}
|
channelId={channel.id}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ describe('components/drafts/drafts_row', () => {
|
|||||||
user: {} as UserProfile,
|
user: {} as UserProfile,
|
||||||
status: {} as UserStatus['status'],
|
status: {} as UserStatus['status'],
|
||||||
displayName: 'test',
|
displayName: 'test',
|
||||||
|
isRemote: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should match snapshot for channel draft', () => {
|
it('should match snapshot for channel draft', () => {
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ type Props = {
|
|||||||
status: UserStatus['status'];
|
status: UserStatus['status'];
|
||||||
displayName: string;
|
displayName: string;
|
||||||
draft: Draft;
|
draft: Draft;
|
||||||
|
isRemote: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DraftRow({draft, user, status, displayName}: Props) {
|
function DraftRow({draft, user, status, displayName, isRemote}: Props) {
|
||||||
switch (draft.type) {
|
switch (draft.type) {
|
||||||
case 'channel':
|
case 'channel':
|
||||||
return (
|
return (
|
||||||
@@ -26,6 +27,7 @@ function DraftRow({draft, user, status, displayName}: Props) {
|
|||||||
user={user}
|
user={user}
|
||||||
status={status}
|
status={status}
|
||||||
displayName={displayName}
|
displayName={displayName}
|
||||||
|
isRemote={isRemote}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'thread':
|
case 'thread':
|
||||||
@@ -37,6 +39,7 @@ function DraftRow({draft, user, status, displayName}: Props) {
|
|||||||
user={user}
|
user={user}
|
||||||
status={status}
|
status={status}
|
||||||
displayName={displayName}
|
displayName={displayName}
|
||||||
|
isRemote={isRemote}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ describe('components/drafts/drafts', () => {
|
|||||||
displayName: 'display_name',
|
displayName: 'display_name',
|
||||||
status: {} as UserStatus['status'],
|
status: {} as UserStatus['status'],
|
||||||
localDraftsAreEnabled: true,
|
localDraftsAreEnabled: true,
|
||||||
|
draftRemotes: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should match snapshot', () => {
|
it('should match snapshot', () => {
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ type Props = {
|
|||||||
displayName: string;
|
displayName: string;
|
||||||
status: UserStatus['status'];
|
status: UserStatus['status'];
|
||||||
localDraftsAreEnabled: boolean;
|
localDraftsAreEnabled: boolean;
|
||||||
|
draftRemotes: Record<string, boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Drafts({
|
function Drafts({
|
||||||
displayName,
|
displayName,
|
||||||
drafts,
|
drafts,
|
||||||
|
draftRemotes,
|
||||||
status,
|
status,
|
||||||
user,
|
user,
|
||||||
localDraftsAreEnabled,
|
localDraftsAreEnabled,
|
||||||
@@ -75,6 +77,7 @@ function Drafts({
|
|||||||
key={d.key}
|
key={d.key}
|
||||||
displayName={displayName}
|
displayName={displayName}
|
||||||
draft={d}
|
draft={d}
|
||||||
|
isRemote={draftRemotes[d.key]}
|
||||||
user={user}
|
user={user}
|
||||||
status={status}
|
status={status}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ function makeMapStateToProps() {
|
|||||||
return {
|
return {
|
||||||
displayName: displayUsername(user, getTeammateNameDisplaySetting(state)),
|
displayName: displayUsername(user, getTeammateNameDisplaySetting(state)),
|
||||||
drafts: getDrafts(state),
|
drafts: getDrafts(state),
|
||||||
|
draftRemotes: state.views.drafts.remotes,
|
||||||
status,
|
status,
|
||||||
user,
|
user,
|
||||||
localDraftsAreEnabled: localDraftsAreEnabled(state),
|
localDraftsAreEnabled: localDraftsAreEnabled(state),
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ exports[`components/drafts/drafts_row should match snapshot for channel draft 1`
|
|||||||
displayName=""
|
displayName=""
|
||||||
draftId=""
|
draftId=""
|
||||||
id={Object {}}
|
id={Object {}}
|
||||||
|
isRemote={false}
|
||||||
rootId=""
|
rootId=""
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
thread={
|
thread={
|
||||||
@@ -98,6 +99,7 @@ exports[`components/drafts/drafts_row should match snapshot for undefined thread
|
|||||||
displayName=""
|
displayName=""
|
||||||
draftId=""
|
draftId=""
|
||||||
id={Object {}}
|
id={Object {}}
|
||||||
|
isRemote={false}
|
||||||
rootId=""
|
rootId=""
|
||||||
status={Object {}}
|
status={Object {}}
|
||||||
thread={null}
|
thread={null}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ describe('components/drafts/drafts_row', () => {
|
|||||||
type: 'thread' as 'channel' | 'thread',
|
type: 'thread' as 'channel' | 'thread',
|
||||||
user: {} as UserProfile,
|
user: {} as UserProfile,
|
||||||
value: {} as PostDraft,
|
value: {} as PostDraft,
|
||||||
|
isRemote: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should match snapshot for channel draft', () => {
|
it('should match snapshot for channel draft', () => {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Props = {
|
|||||||
type: 'channel' | 'thread';
|
type: 'channel' | 'thread';
|
||||||
user: UserProfile;
|
user: UserProfile;
|
||||||
value: PostDraft;
|
value: PostDraft;
|
||||||
|
isRemote: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ThreadDraft({
|
function ThreadDraft({
|
||||||
@@ -45,6 +46,7 @@ function ThreadDraft({
|
|||||||
type,
|
type,
|
||||||
user,
|
user,
|
||||||
value,
|
value,
|
||||||
|
isRemote,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
@@ -107,7 +109,7 @@ function ThreadDraft({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
timestamp={value.updateAt}
|
timestamp={value.updateAt}
|
||||||
remote={value.remote || false}
|
remote={isRemote || false}
|
||||||
/>
|
/>
|
||||||
<PanelBody
|
<PanelBody
|
||||||
channelId={channel.id}
|
channelId={channel.id}
|
||||||
|
|||||||
@@ -144,7 +144,6 @@ function migrateDrafts(state: any) {
|
|||||||
createAt: timestamp.getTime(),
|
createAt: timestamp.getTime(),
|
||||||
updateAt: timestamp.getTime(),
|
updateAt: timestamp.getTime(),
|
||||||
show: true,
|
show: true,
|
||||||
remote: false,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
25
webapp/channels/src/reducers/views/drafts.ts
Обычный файл
25
webapp/channels/src/reducers/views/drafts.ts
Обычный файл
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {combineReducers} from 'redux';
|
||||||
|
import {GenericAction} from 'mattermost-redux/types/actions';
|
||||||
|
import {ActionTypes} from 'utils/constants';
|
||||||
|
|
||||||
|
function remotes(state: Record<string, boolean> = {}, action: GenericAction) {
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionTypes.SET_DRAFT_SOURCE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
[action.data.key]: action.data.isRemote,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default combineReducers({
|
||||||
|
|
||||||
|
// object that stores global draft keys indicating whether the draft came from a WebSocket event.
|
||||||
|
remotes,
|
||||||
|
|
||||||
|
});
|
||||||
@@ -28,6 +28,7 @@ import addChannelDropdown from './add_channel_dropdown';
|
|||||||
import addChannelCtaDropdown from './add_channel_cta_dropdown';
|
import addChannelCtaDropdown from './add_channel_cta_dropdown';
|
||||||
import threads from './threads';
|
import threads from './threads';
|
||||||
import onboardingTasks from './onboarding_tasks';
|
import onboardingTasks from './onboarding_tasks';
|
||||||
|
import drafts from './drafts';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
admin,
|
admin,
|
||||||
@@ -55,4 +56,5 @@ export default combineReducers({
|
|||||||
onboardingTasks,
|
onboardingTasks,
|
||||||
threads,
|
threads,
|
||||||
productMenu,
|
productMenu,
|
||||||
|
drafts,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ export type PostDraft = {
|
|||||||
createAt: number;
|
createAt: number;
|
||||||
updateAt: number;
|
updateAt: number;
|
||||||
show?: boolean;
|
show?: boolean;
|
||||||
remote?: boolean;
|
|
||||||
metadata?: {
|
metadata?: {
|
||||||
priority?: {
|
priority?: {
|
||||||
priority: PostPriority|'';
|
priority: PostPriority|'';
|
||||||
|
|||||||
@@ -62,6 +62,12 @@ export type ViewsState = {
|
|||||||
toastStatus: boolean;
|
toastStatus: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
drafts: {
|
||||||
|
remotes: {
|
||||||
|
[storageKey: string]: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
rhs: RhsViewState;
|
rhs: RhsViewState;
|
||||||
|
|
||||||
rhsSuppressed: boolean;
|
rhsSuppressed: boolean;
|
||||||
|
|||||||
@@ -337,6 +337,8 @@ export const ActionTypes = keyMirror({
|
|||||||
RECEIVED_PLUGIN_INSIGHT: null,
|
RECEIVED_PLUGIN_INSIGHT: null,
|
||||||
SET_EDIT_CHANNEL_MEMBERS: null,
|
SET_EDIT_CHANNEL_MEMBERS: null,
|
||||||
NEEDS_LOGGED_IN_LIMIT_REACHED_CHECK: null,
|
NEEDS_LOGGED_IN_LIMIT_REACHED_CHECK: null,
|
||||||
|
|
||||||
|
SET_DRAFT_SOURCE: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const PostRequestTypes = keyMirror({
|
export const PostRequestTypes = keyMirror({
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user