From 6c45dcb1092e2f441535df23db0018614c34af7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Tue, 7 Jun 2022 18:25:53 +0200 Subject: [PATCH] TypeScript, FC (reducers, search) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/components/dropdown_menu.tsx | 2 + app/soapbox/components/hashtag.tsx | 20 +- app/soapbox/components/pullable.tsx | 2 +- app/soapbox/components/ui/column/column.tsx | 2 +- .../containers/dropdown_menu_container.ts | 2 +- .../features/compose/components/search.tsx | 4 +- .../compose/components/search_results.js | Bin 6408 -> 0 bytes .../compose/components/search_results.tsx | 172 ++++++++++++++++++ .../containers/search_results_container.js | Bin 1345 -> 0 bytes .../containers/status_check_box_container.js | Bin 606 -> 524 bytes .../features/search/components/header.js | Bin 1539 -> 0 bytes app/soapbox/features/search/index.tsx | 4 +- .../__tests__/trends-panel.test.tsx | 38 ++-- .../ui/components/account_note_modal.js | Bin 2932 -> 0 bytes .../ui/components/account_note_modal.tsx | 68 +++++++ .../{actions_modal.js => actions_modal.tsx} | Bin 2767 -> 2847 bytes app/soapbox/features/ui/components/column.js | Bin 966 -> 0 bytes app/soapbox/features/ui/components/column.tsx | 36 ++++ .../ui/components/column_forbidden.js | Bin 794 -> 0 bytes .../ui/components/column_forbidden.tsx | 23 +++ .../features/ui/components/column_header.js | Bin 1016 -> 0 bytes .../features/ui/components/column_header.tsx | 47 +++++ .../{column_loading.js => column_loading.tsx} | Bin .../modals/report-modal/report-modal.tsx | 12 +- .../report-modal/steps/other-actions-step.tsx | 8 +- .../modals/report-modal/steps/reason-step.tsx | 7 +- .../features/ui/components/mute_modal.js | Bin 3123 -> 3106 bytes .../features/ui/components/trends-panel.tsx | 9 +- app/soapbox/reducers/__tests__/modals-test.js | Bin 1346 -> 1338 bytes .../reducers/__tests__/reports-test.js | Bin 495 -> 379 bytes app/soapbox/reducers/__tests__/trends-test.js | Bin 321 -> 228 bytes app/soapbox/reducers/account_notes.ts | 4 +- app/soapbox/reducers/{modals.js => modals.ts} | Bin 757 -> 1019 bytes .../reducers/{reports.js => reports.ts} | Bin 2718 -> 2946 bytes app/soapbox/reducers/{search.js => search.ts} | Bin 3177 -> 4129 bytes .../reducers/{security.tsx => security.ts} | 3 +- app/soapbox/reducers/trending_statuses.js | Bin 865 -> 0 bytes app/soapbox/reducers/trending_statuses.ts | 37 ++++ app/soapbox/reducers/trends.js | Bin 736 -> 0 bytes app/soapbox/reducers/trends.ts | 47 +++++ 40 files changed, 490 insertions(+), 57 deletions(-) delete mode 100644 app/soapbox/features/compose/components/search_results.js create mode 100644 app/soapbox/features/compose/components/search_results.tsx delete mode 100644 app/soapbox/features/compose/containers/search_results_container.js delete mode 100644 app/soapbox/features/search/components/header.js delete mode 100644 app/soapbox/features/ui/components/account_note_modal.js create mode 100644 app/soapbox/features/ui/components/account_note_modal.tsx rename app/soapbox/features/ui/components/{actions_modal.js => actions_modal.tsx} (71%) delete mode 100644 app/soapbox/features/ui/components/column.js create mode 100644 app/soapbox/features/ui/components/column.tsx delete mode 100644 app/soapbox/features/ui/components/column_forbidden.js create mode 100644 app/soapbox/features/ui/components/column_forbidden.tsx delete mode 100644 app/soapbox/features/ui/components/column_header.js create mode 100644 app/soapbox/features/ui/components/column_header.tsx rename app/soapbox/features/ui/components/{column_loading.js => column_loading.tsx} (100%) rename app/soapbox/reducers/{modals.js => modals.ts} (50%) rename app/soapbox/reducers/{reports.js => reports.ts} (54%) rename app/soapbox/reducers/{search.js => search.ts} (56%) rename app/soapbox/reducers/{security.tsx => security.ts} (97%) delete mode 100644 app/soapbox/reducers/trending_statuses.js create mode 100644 app/soapbox/reducers/trending_statuses.ts delete mode 100644 app/soapbox/reducers/trends.js create mode 100644 app/soapbox/reducers/trends.ts diff --git a/app/soapbox/components/dropdown_menu.tsx b/app/soapbox/components/dropdown_menu.tsx index d56a72a018..7a59e49320 100644 --- a/app/soapbox/components/dropdown_menu.tsx +++ b/app/soapbox/components/dropdown_menu.tsx @@ -26,6 +26,8 @@ export interface MenuItem { icon: string, count?: number, destructive?: boolean, + meta?: string, + active?: boolean, } export type Menu = Array; diff --git a/app/soapbox/components/hashtag.tsx b/app/soapbox/components/hashtag.tsx index c8e45a084a..8206f3f62f 100644 --- a/app/soapbox/components/hashtag.tsx +++ b/app/soapbox/components/hashtag.tsx @@ -10,24 +10,26 @@ import { shortNumberFormat } from '../utils/numbers'; import Permalink from './permalink'; import { HStack, Stack, Text } from './ui'; -import type { Map as ImmutableMap } from 'immutable'; +import type { Hashtag as HashtagEntity } from 'soapbox/reducers/search'; +import type { TrendingHashtag } from 'soapbox/reducers/trends'; interface IHashtag { - hashtag: ImmutableMap, + hashtag: HashtagEntity | TrendingHashtag, } const Hashtag: React.FC = ({ hashtag }) => { - const count = Number(hashtag.getIn(['history', 0, 'accounts'])); - const brandColor = useSelector((state) => getSoapboxConfig(state).get('brandColor')); + const history = (hashtag as TrendingHashtag).history; + const count = Number(history?.get(0)?.accounts); + const brandColor = useSelector((state) => getSoapboxConfig(state).brandColor); return ( - - #{hashtag.get('name')} + + #{hashtag.name} - {hashtag.get('history') && ( + {history && ( = ({ hashtag }) => { )} - {hashtag.get('history') && ( + {history && (
) => day.get('uses')).toArray()} + data={history.reverse().map((day) => +day.uses).toArray()} > diff --git a/app/soapbox/components/pullable.tsx b/app/soapbox/components/pullable.tsx index 0304a1d465..03840d2c1f 100644 --- a/app/soapbox/components/pullable.tsx +++ b/app/soapbox/components/pullable.tsx @@ -3,7 +3,7 @@ import React from 'react'; import PullToRefresh from './pull-to-refresh'; interface IPullable { - children: JSX.Element, + children: React.ReactNode, } /** diff --git a/app/soapbox/components/ui/column/column.tsx b/app/soapbox/components/ui/column/column.tsx index dde81736a6..5ac4f350e0 100644 --- a/app/soapbox/components/ui/column/column.tsx +++ b/app/soapbox/components/ui/column/column.tsx @@ -7,7 +7,7 @@ import { useSoapboxConfig } from 'soapbox/hooks'; import { Card, CardBody, CardHeader, CardTitle } from '../card/card'; -interface IColumn { +export interface IColumn { /** Route the back button goes to. */ backHref?: string, /** Column title text. */ diff --git a/app/soapbox/containers/dropdown_menu_container.ts b/app/soapbox/containers/dropdown_menu_container.ts index d3e7149e40..b047edfff5 100644 --- a/app/soapbox/containers/dropdown_menu_container.ts +++ b/app/soapbox/containers/dropdown_menu_container.ts @@ -10,7 +10,7 @@ import type { DropdownPlacement, IDropdown } from 'soapbox/components/dropdown_m import type { RootState } from 'soapbox/store'; const mapStateToProps = (state: RootState) => ({ - isModalOpen: Boolean(state.modals.size && state.modals.last().modalType === 'ACTIONS'), + isModalOpen: Boolean(state.modals.size && state.modals.last()!.modalType === 'ACTIONS'), dropdownPlacement: state.dropdown_menu.placement, openDropdownId: state.dropdown_menu.openId, openedViaKeyboard: state.dropdown_menu.keyboard, diff --git a/app/soapbox/features/compose/components/search.tsx b/app/soapbox/features/compose/components/search.tsx index d68f82bc2b..e70786cb7b 100644 --- a/app/soapbox/features/compose/components/search.tsx +++ b/app/soapbox/features/compose/components/search.tsx @@ -50,8 +50,8 @@ const Search = (props: ISearch) => { const history = useHistory(); const intl = useIntl(); - const value = useAppSelector((state) => state.search.get('value')); - const submitted = useAppSelector((state) => state.search.get('submitted')); + const value = useAppSelector((state) => state.search.value); + const submitted = useAppSelector((state) => state.search.submitted); const debouncedSubmit = debounce(() => { dispatch(submitSearch()); diff --git a/app/soapbox/features/compose/components/search_results.js b/app/soapbox/features/compose/components/search_results.js deleted file mode 100644 index e4dfa936b34ecf461b9960554b8dc42207c96bc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6408 zcmd5>ZExE)5dNNDaVv_-24XuH1`P15U|qMO!PcQ@@@*JWTB2jFvgC<$+Dz4d-yL5> zQkD~E-LMuYYLRyjA0F?Gtk`U;T0vGYDSu@fE@4$y8%Xp(Ndw7uC&CE5sjKbP-L{k2 z;`c<+fR}m8S*9#TO~3ur#b&cpY+3L=j+UDUH$5TT9<0~h)%-<;d`ezM>xB9!Gs&Eg zC(yvls@^cAc>bD8$!<8bA=QZ}RS}Bkd?iY5W#uV|@(-S=3zQmGbcTAx3LB{z-NVl&6McK(+7bxff8n|Lh+0hzM-3c%KJj<$Gsa{m2 zVz|S4kEtD(GiD^OGbidnE)`Qdc?5>kf}aC8QAh;HWtPup5vg9~Cci2?tU{b7D6tGN8m_5?BgkNPt^b?D!nI zj5L+17Uc~Y2f*5M9zZ*Q>4t5mLcZmH?nKRVBQJN$jiBrj0xqknFw?j%R_2C$D6!g= z**+F8FxBw5Vu-Va@)t<-Jl~Xfqpq?2ued{f2ziFK;xNc zAg}UA(%G#i{*Vx5)Ami)u>Oo?0WMk06vW2QzuQ3KjlfFA{t!~~2KjUNVVR$OK4tDY@K2msI$ zGn(PGS>^{;cMv9XU`9ZbokF}PtP5#i3B5xAqahUEP@?$_vFVQ?M86b<)?DLFSGsW8 zG%|AOsmnBD;{l|EB_Dld9$Md=OlZqd(&eZ?mD&wVQQedS)wznWA4ARMt^of?YECl= zR4uh`>a(c1bQs_tNzG{vQ0u08)PA>zU2`m?B`kECpwB#Q^gpdWvRi(Eevme?-?T70 z?>XL{zv&cu>XIdTp38!LC#0z^mz+XBUDy%oVFrA);0k@3%AC#nL<@k1apyMTSFDiS zPZXF7c<#T;%IaD__A@~n;hW18_Da09rC7lzHWZ|38hEY?Ysw>zoUJC)8?Lo# zcAFCKGr7o^s_NuCP(h{sJt&$*C&?`k_Ur^SHAmg0`=loycbRE&wdPoX8U8IR*y@hc zc@|(LfhP_2G@JHGA4jJWnKliUo_aGk-5IoPwA?J*%VLK6_XFNdw2H2m#^;B^waez- z-Uq_fNgf%lPTYs9-N9b;Imvu-!D5B?Ve@7PTgDYoYMapj<(r%jl#lL$VT5Z_wJCkQc?sp zdmYE8PjSl;KUPM0$`q66J{?zY^MLs?^?UE0_HP^Wr;Tm_+IO*%kQC$ce~II zZQLgomh0-nz2cna>jozb&PX%f7 z^;s;@z1gQt_fzTzLOMqGC&30u%&!3fbiF|CKb6Wj*Fl^3(v TLA_oFx3Ep5Zf?-`+mpWmcfb~? diff --git a/app/soapbox/features/compose/components/search_results.tsx b/app/soapbox/features/compose/components/search_results.tsx new file mode 100644 index 0000000000..91e7ff2877 --- /dev/null +++ b/app/soapbox/features/compose/components/search_results.tsx @@ -0,0 +1,172 @@ +import classNames from 'classnames'; +import React from 'react'; +import { useEffect } from 'react'; +import { FormattedMessage, useIntl } from 'react-intl'; +import { defineMessages } from 'react-intl'; + +import { expandSearch, setFilter } from 'soapbox/actions/search'; +import { fetchTrendingStatuses } from 'soapbox/actions/trending_statuses'; +import Hashtag from 'soapbox/components/hashtag'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import { Tabs } from 'soapbox/components/ui'; +import AccountContainer from 'soapbox/containers/account_container'; +import StatusContainer from 'soapbox/containers/status_container'; +import PlaceholderAccount from 'soapbox/features/placeholder/components/placeholder_account'; +import PlaceholderHashtag from 'soapbox/features/placeholder/components/placeholder_hashtag'; +import PlaceholderStatus from 'soapbox/features/placeholder/components/placeholder_status'; +import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; + +import type { SearchFilter } from 'soapbox/reducers/search'; + +const messages = defineMessages({ + accounts: { id: 'search_results.accounts', defaultMessage: 'People' }, + statuses: { id: 'search_results.statuses', defaultMessage: 'Posts' }, + hashtags: { id: 'search_results.hashtags', defaultMessage: 'Hashtags' }, +}); + +const SearchResults = () => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + + const value = useAppSelector((state) => state.search.submittedValue); + const results = useAppSelector((state) => state.search.results); + const suggestions = useAppSelector((state) => state.suggestions.items); + const trendingStatuses = useAppSelector((state) => state.trending_statuses.items); + const trends = useAppSelector((state) => state.trends.items); + const submitted = useAppSelector((state) => state.search.submitted); + const selectedFilter = useAppSelector((state) => state.search.filter); + + const handleLoadMore = () => dispatch(expandSearch(selectedFilter)); + + const selectFilter = (newActiveFilter: SearchFilter) => dispatch(setFilter(newActiveFilter)); + + const renderFilterBar = () => { + const items = [ + { + text: intl.formatMessage(messages.accounts), + action: () => selectFilter('accounts'), + name: 'accounts', + }, + { + text: intl.formatMessage(messages.statuses), + action: () => selectFilter('statuses'), + name: 'statuses', + }, + { + text: intl.formatMessage(messages.hashtags), + action: () => selectFilter('hashtags'), + name: 'hashtags', + }, + ]; + + return ; + }; + + useEffect(() => { + dispatch(fetchTrendingStatuses()); + }, []); + + let searchResults; + let hasMore = false; + let loaded; + let noResultsMessage; + let placeholderComponent = PlaceholderStatus as React.ComponentType; + + if (selectedFilter === 'accounts') { + hasMore = results.accountsHasMore; + loaded = results.accountsLoaded; + placeholderComponent = PlaceholderAccount; + + if (results.accounts && results.accounts.size > 0) { + searchResults = results.accounts.map(accountId => ); + } else if (!submitted && suggestions && !suggestions.isEmpty()) { + searchResults = suggestions.map(suggestion => ); + } else if (loaded) { + noResultsMessage = ( +
+ +
+ ); + } + } + + if (selectedFilter === 'statuses') { + hasMore = results.statusesHasMore; + loaded = results.statusesLoaded; + + if (results.statuses && results.statuses.size > 0) { + searchResults = results.statuses.map((statusId: string) => ( + // @ts-ignore + + )); + } else if (!submitted && trendingStatuses && !trendingStatuses.isEmpty()) { + searchResults = trendingStatuses.map((statusId: string) => ( + // @ts-ignore + + )); + } else if (loaded) { + noResultsMessage = ( +
+ +
+ ); + } + } + + if (selectedFilter === 'hashtags') { + hasMore = results.hashtagsHasMore; + loaded = results.hashtagsLoaded; + placeholderComponent = PlaceholderHashtag; + + if (results.hashtags && results.hashtags.size > 0) { + searchResults = results.hashtags.map(hashtag => ); + } else if (!submitted && suggestions && !suggestions.isEmpty()) { + searchResults = trends.map(hashtag => ); + } else if (loaded) { + noResultsMessage = ( +
+ +
+ ); + } + } + + return ( + <> + {renderFilterBar()} + + {noResultsMessage || ( + + {searchResults || []} + + )} + + ); +}; + +export default SearchResults; diff --git a/app/soapbox/features/compose/containers/search_results_container.js b/app/soapbox/features/compose/containers/search_results_container.js deleted file mode 100644 index e284060d9b70df6feb42208a1a24f333e84d31a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1345 zcmZ`(!HU~35WVLs<|Y~3loq}$Fq51&w4W3cpaf!f&?ghN&OFAl5zEFN|{op5;Wl&OxWT=|{@p?}tmM>p}v zs_xC656srq(19Y7B_@R$effUuPbZ`Z$)VEJYNGkN?k$iDzDs4_juY6BPcSZaN ze5Db&lsfT^kOka^K<{-!hk6Vz+A_4`CsN;d8XLIZA4NT71V$wRBU zP%pmNAI^3Jj}VGNc>D^VI|x%@kmjE!y>S0uCa*EFr z+LqWR(rv=&!s|>MJ(;Q`Y}gT44I6%+Sw{yq=n~ArC5K0^!dkH# V)6*wcUd)3zpROm9$t$a~*nhq*)h7S| diff --git a/app/soapbox/features/report/containers/status_check_box_container.js b/app/soapbox/features/report/containers/status_check_box_container.js index 75daf7e2d61a9091681e8b513382bd8e3b1f5ab0..49bcf70f33884653318991abaa3235a7b09f7617 100644 GIT binary patch delta 35 qcmcb|(!;XRke5-cD77HJsH9jgFST5+xFoTpv^YL9rFe2F<4XYGFAZY= delta 117 zcmeBSxyNFdnOl%wRH9I=5S&_~kXWqXnVVZ$l9-f}3gXu)q!s1oDyV0|1l6s%Ht;f< xr>B;9=4nK$7o~zU7pvf&U487-9a3?!JouJn>?xn-90$WjR-7Z5BC^nM_vn4~4gA76b`$)-ON|812 zA(S5V9v>yjy3xkLv(e4V-v%vgjjkbSD9#)&BzH3zFyB!WuG=^Kf82Vk>(+@)h0m?Q z2Tgc|D#B*6hhz<5vZ4o#hn(QEHnngL%Wr6{*dd&!beUAHn!*dM6q2MEWw30IQ`nO@ ze3k0YB}}&tO;+lfuroT!I;chS!wH8kn*FelgXIwNdq__+fP<)7{1_G&J9LjK{he48 zrr0MpkofK7b$&xo+iq&frCf&(5TA0Mvy4hu3tv!_XaJ86RcYahxu+S^kUm)ew=1+S z2NpU=9s0Vk&PcUmX_2@Qu+h5W?K9~J2UFqQX@k^X!GRisN#5N%uOGs?Md#ag~ z(w;A{y-n*GecQbc0IdB(EUZ6<&vmU)pxUbH89i~gp85b_RmubS=01rU^X|@Md*A5f zzC*o(Tdy5m33@ro38~Ob@+fnEdzF9^rK>RG^e7476c@&R^}p3}e>+jOq!K3K{|X{L znjG0yR`kMb#CU0hC<@&ww_aO%$WkkBNk!E~S??P&;mc?c#iU%(s-FT*=gG2rvp_>k z9`J!*U1&^LxFGlWZ)TG$`#!D>+O~3b;dGNgiCaNYH^TDdg%_8jb-~}&vJ(_ {
- +
); diff --git a/app/soapbox/features/ui/components/__tests__/trends-panel.test.tsx b/app/soapbox/features/ui/components/__tests__/trends-panel.test.tsx index d122090c2d..6701c928d1 100644 --- a/app/soapbox/features/ui/components/__tests__/trends-panel.test.tsx +++ b/app/soapbox/features/ui/components/__tests__/trends-panel.test.tsx @@ -1,4 +1,4 @@ -import { Map as ImmutableMap, fromJS } from 'immutable'; +import { List as ImmutableList } from 'immutable'; import React from 'react'; import { render, screen } from '../../../../jest/test-helpers'; @@ -7,16 +7,16 @@ import TrendsPanel from '../trends-panel'; describe('', () => { it('renders trending hashtags', () => { const store = { - trends: ImmutableMap({ - items: fromJS([{ + trends: { + items: ImmutableList([{ name: 'hashtag 1', - history: [{ + history: ImmutableList([{ day: '1652745600', uses: '294', accounts: '180', - }], + }]), }]), - }), + }, }; render(, null, store); @@ -27,18 +27,18 @@ describe('', () => { it('renders multiple trends', () => { const store = { - trends: ImmutableMap({ - items: fromJS([ + trends: { + items: ImmutableList([ { name: 'hashtag 1', - history: [{ accounts: [] }], + history: ImmutableList([{ accounts: [] }]), }, { name: 'hashtag 2', - history: [{ accounts: [] }], + history: ImmutableList([{ accounts: [] }]), }, ]), - }), + }, }; render(, null, store); @@ -47,18 +47,18 @@ describe('', () => { it('respects the limit prop', () => { const store = { - trends: ImmutableMap({ - items: fromJS([ + trends: { + items: ImmutableList([ { name: 'hashtag 1', - history: [{ accounts: [] }], + history: ImmutableList([{ accounts: [] }]), }, { name: 'hashtag 2', - history: [{ accounts: [] }], + history: ImmutableList([{ accounts: [] }]), }, ]), - }), + }, }; render(, null, store); @@ -67,9 +67,9 @@ describe('', () => { it('renders empty', () => { const store = { - trends: ImmutableMap({ - items: fromJS([]), - }), + trends: { + items: ImmutableList([]), + }, }; render(, null, store); diff --git a/app/soapbox/features/ui/components/account_note_modal.js b/app/soapbox/features/ui/components/account_note_modal.js deleted file mode 100644 index 9242b7b8f2417016293c5ea2a5872e144c3507d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2932 zcma)8QE%Hg41UkA;M42?se{A4Wp&Y_!w$ot#jy6}a5x+kn@M!FrJN;qExi2qk&%DF)d~Wpq@pX>|HjSY&7p zRCtHRh%K50NcA5U_LH*J0zT@d7S>`Jj^PkTxsYTOhbpvE<%HC^>x4N!T*#($(T}vCC46%$B`?Y>q5_+kXpbz;frQ7;>K901I>^h@t$@w zfPEzj-07;sW(6I{as^4q^Iy(0iwu$lM-XjgLv6_RUIT$;CV|@ES(aEPa9B`eBcAbm zNIp3i>w(|1^I=Z#1A0pMPV677u=uFC^9&`D&LO`7#_z4RBPBUZIZ8QJZ&#m0G8~wL zIW_>Kd2sz;rP{8*on{pMlS==d@M0)|1WRf8H+D+?nRE64fyEV!;8GWlT8=M$J8WME zSyIptHIV(w(1LwH<%k7n(6)^tq9(k)pB*CF_aCI$3tQ|)*30mw=RSntG5~0GtJOv} zHPyzy0q7mllNn3rR2FulYWMCuMCY8x={o1-oA1_*cN(%igWyN=Ke&u|2$ZJ+U!2^9 zo`-AdHP)Jx8|X!=o=2Ap1IpWB9o$v%zhkZ)2iZ}oiFk) zSvpzpm3h;C=<5-yu?-EO2gtG?$2gk@w=V#7LRt0l?r$f>a5L`v((a_mm`{^&(?%#$ z%&cf=UbAOWwdh*nFvj%CFp(dCqiA6SxVaM%eFx#V5=GoBC|EL1dCTHUzao_8mdo;T-h zop;PmMi?nX*o0}nWiwuG^YhN64`N+mNdY4Id)uo4`K9|Nusf_VPwJMwg_7}*D1V#W z9U(lW_AlK+Arw3z?!kS;fLQC+x*|hsuyMq{>b9W|3F=NJ1-{CvVry6 { + const intl = useIntl(); + const dispatch = useAppDispatch(); + + const isSubmitting = useAppSelector((state) => state.account_notes.edit.isSubmitting); + const account = useAppSelector((state) => getAccount(state, state.account_notes.edit.account!)); + const comment = useAppSelector((state) => state.account_notes.edit.comment); + + const onClose = () => { + dispatch(closeModal('ACCOUNT_NOTE')); + }; + + const handleCommentChange: React.ChangeEventHandler = e => { + dispatch(changeAccountNoteComment(e.target.value)); + }; + + const handleSubmit = () => { + dispatch(submitAccountNote()); + }; + + const handleKeyDown: React.KeyboardEventHandler = e => { + if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { + handleSubmit(); + } + }; + + return ( + } + onClose={onClose} + confirmationAction={handleSubmit} + confirmationText={intl.formatMessage(messages.save)} + confirmationDisabled={isSubmitting} + > + + + + +