From 39ec761e1a61d60381c8c88feb766ff9b477af7c Mon Sep 17 00:00:00 2001
From: Jed Fox <git@jedfox.com>
Date: Wed, 31 Aug 2022 16:28:13 -0400
Subject: [PATCH] =?UTF-8?q?Make=20=E2=80=9CManage=20Payees=E2=80=9D=20a=20?=
 =?UTF-8?q?page?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/components/FinancesApp.js             |   2 +
 .../desktop-client/src/components/Modals.js   |  15 --
 .../src/components/accounts/Account.js        |   5 -
 .../components/accounts/TransactionList.js    |  11 +-
 .../src/components/payees/ManagePayeesPage.js |  19 ++
 .../components/payees/ManagePayeesWithData.js |   4 -
 packages/desktop-electron/index.js            |   5 +-
 packages/desktop-electron/menu.js             |  14 --
 packages/loot-design/src/components/payees.js | 174 ++++++++----------
 .../loot-design/src/components/sidebar.js     |  17 +-
 10 files changed, 123 insertions(+), 143 deletions(-)
 create mode 100644 packages/desktop-client/src/components/payees/ManagePayeesPage.js

diff --git a/packages/desktop-client/src/components/FinancesApp.js b/packages/desktop-client/src/components/FinancesApp.js
index 988f58fa2..8bd87edc0 100644
--- a/packages/desktop-client/src/components/FinancesApp.js
+++ b/packages/desktop-client/src/components/FinancesApp.js
@@ -36,6 +36,7 @@ import Modals from './Modals';
 import Notifications from './Notifications';
 import GlobalKeys from './GlobalKeys';
 import { ManageRulesPage } from './ManageRulesPage';
+import { ManagePayeesPage } from './payees/ManagePayeesPage';
 // import Debugger from './Debugger';
 
 function URLBar() {
@@ -98,6 +99,7 @@ function Routes({ location }) {
         />
 
         <Route path="/rules" exact component={ManageRulesPage} />
+        <Route path="/payees" exact component={ManagePayeesPage} />
         <Route path="/tools/fix-splits" exact component={FixSplitsTool} />
 
         <Route
diff --git a/packages/desktop-client/src/components/Modals.js b/packages/desktop-client/src/components/Modals.js
index ee029e6df..72677d0d0 100644
--- a/packages/desktop-client/src/components/Modals.js
+++ b/packages/desktop-client/src/components/Modals.js
@@ -148,21 +148,6 @@ function Modals({
           }}
         />
 
-        <Route
-          path="/manage-payees"
-          render={() => {
-            return (
-              <ManagePayeesWithData
-                history={history}
-                modalProps={modalProps}
-                initialSelectedIds={
-                  options.selectedPayee ? [options.selectedPayee] : undefined
-                }
-              />
-            );
-          }}
-        />
-
         <Route
           path="/manage-rules"
           render={() => {
diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index 9702010a5..4c2a97595 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -1363,10 +1363,6 @@ class AccountInternal extends React.PureComponent {
     return this.props.matchedTransactions.includes(id);
   };
 
-  onManagePayees = id => {
-    this.props.pushModal('manage-payees', { selectedPayee: id });
-  };
-
   onCreatePayee = name => {
     let trimmed = name.trim();
     if (trimmed !== '') {
@@ -1717,7 +1713,6 @@ class AccountInternal extends React.PureComponent {
                     onCloseAddTransaction={() =>
                       this.setState({ isAdding: false })
                     }
-                    onManagePayees={this.onManagePayees}
                     onCreatePayee={this.onCreatePayee}
                   />
                 </View>
diff --git a/packages/desktop-client/src/components/accounts/TransactionList.js b/packages/desktop-client/src/components/accounts/TransactionList.js
index a07c31f80..69a8c0055 100644
--- a/packages/desktop-client/src/components/accounts/TransactionList.js
+++ b/packages/desktop-client/src/components/accounts/TransactionList.js
@@ -10,6 +10,7 @@ import {
 import { send } from 'loot-core/src/platform/client/fetch';
 import { getChangedValues, applyChanges } from 'loot-core/src/shared/util';
 import { TransactionTable } from './TransactionsTable';
+import { useHistory } from 'react-router';
 const uuid = require('loot-core/src/platform/uuid');
 
 // When data changes, there are two ways to update the UI:
@@ -75,13 +76,13 @@ export default function TransactionList({
   onRefetch,
   onRefetchUpToRow,
   onCloseAddTransaction,
-  onManagePayees,
   onCreatePayee
 }) {
   let dispatch = useDispatch();
   let table = useRef();
   let transactionsLatest = useRef();
   let scrollTo = useRef();
+  let history = useHistory();
 
   // useEffect(() => {
   //   if (scrollTo.current) {
@@ -157,6 +158,14 @@ export default function TransactionList({
     return newTransaction;
   }, []);
 
+  let onManagePayees = useCallback(
+    id => {
+      debugger;
+      history.push('/payees', { selectedPayee: id });
+    },
+    [history]
+  );
+
   return (
     <TransactionTable
       ref={tableRef}
diff --git a/packages/desktop-client/src/components/payees/ManagePayeesPage.js b/packages/desktop-client/src/components/payees/ManagePayeesPage.js
new file mode 100644
index 000000000..e0237051b
--- /dev/null
+++ b/packages/desktop-client/src/components/payees/ManagePayeesPage.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import ManagePayeesWithData from './ManagePayeesWithData';
+import { Page } from '../Page';
+import { useLocation } from 'react-router';
+
+export function ManagePayeesPage() {
+  let location = useLocation();
+  return (
+    <Page title="Payees">
+      <ManagePayeesWithData
+        initialSelectedIds={
+          location.state && location.state.selectedPayee
+            ? [location.state.selectedPayee]
+            : null
+        }
+      />
+    </Page>
+  );
+}
diff --git a/packages/desktop-client/src/components/payees/ManagePayeesWithData.js b/packages/desktop-client/src/components/payees/ManagePayeesWithData.js
index c80927f9f..e3e2f1a5b 100644
--- a/packages/desktop-client/src/components/payees/ManagePayeesWithData.js
+++ b/packages/desktop-client/src/components/payees/ManagePayeesWithData.js
@@ -7,7 +7,6 @@ import { ManagePayees } from 'loot-design/src/components/payees';
 import { applyChanges } from 'loot-core/src/shared/util';
 
 function ManagePayeesWithData({
-  history,
   modalProps,
   initialSelectedIds,
   lastUndoState,
@@ -52,10 +51,7 @@ function ManagePayeesWithData({
       }
     });
 
-    undo.setUndoState('openModal', 'manage-payees');
-
     return () => {
-      undo.setUndoState('openModal', null);
       unlisten();
     };
   }, []);
diff --git a/packages/desktop-electron/index.js b/packages/desktop-electron/index.js
index 2b83d7053..c0c9ed05d 100644
--- a/packages/desktop-electron/index.js
+++ b/packages/desktop-electron/index.js
@@ -217,10 +217,7 @@ function updateMenu(isBudgetOpen) {
   const fileItems = file.submenu.items;
   fileItems
     .filter(
-      item =>
-        item.label === 'Start Tutorial' ||
-        item.label === 'Manage Payees...' ||
-        item.label === 'Load Backup...'
+      item => item.label === 'Start Tutorial' || item.label === 'Load Backup...'
     )
 
     .map(item => (item.enabled = isBudgetOpen));
diff --git a/packages/desktop-electron/menu.js b/packages/desktop-electron/menu.js
index 9761b0ec9..1b0b7919b 100644
--- a/packages/desktop-electron/menu.js
+++ b/packages/desktop-electron/menu.js
@@ -19,20 +19,6 @@ function getMenu(isDev, createWindow) {
         //     }
         //   }
         // },
-        {
-          label: 'Manage Payees...',
-          enabled: false,
-          click(item, focusedWindow) {
-            if (
-              focusedWindow &&
-              focusedWindow.webContents.getTitle() === 'Actual'
-            ) {
-              focusedWindow.webContents.executeJavaScript(
-                '__actionsForMenu.pushModal("manage-payees")'
-              );
-            }
-          }
-        },
         {
           label: 'Load Backup...',
           enabled: false,
diff --git a/packages/loot-design/src/components/payees.js b/packages/loot-design/src/components/payees.js
index e917ea706..7a4e36d09 100644
--- a/packages/loot-design/src/components/payees.js
+++ b/packages/loot-design/src/components/payees.js
@@ -23,6 +23,7 @@ import { groupById } from 'loot-core/src/shared/util';
 import { colors } from '../style';
 import {
   Table,
+  TableHeader,
   Row,
   Cell,
   InputCell,
@@ -227,7 +228,7 @@ function PayeeTableHeader() {
 
   return (
     <View>
-      <Row
+      <TableHeader
         borderColor={borderColor}
         style={{
           backgroundColor: 'white',
@@ -236,6 +237,7 @@ function PayeeTableHeader() {
           userSelect: 'none'
         }}
         collapsed={true}
+        version="v2"
       >
         <SelectCell
           exposed={true}
@@ -244,7 +246,7 @@ function PayeeTableHeader() {
           onSelect={() => dispatchSelected({ type: 'select-all' })}
         />
         <Cell value="Name" width="flex" />
-      </Row>
+      </TableHeader>
     </View>
   );
 }
@@ -467,108 +469,90 @@ export const ManagePayees = React.forwardRef(
     let payeesById = getPayeesById(payees);
 
     return (
-      <Modal
-        title="Payees"
-        padding={0}
-        {...modalProps}
-        style={[modalProps.style, { flex: 'inherit', maxWidth: '90%' }]}
-      >
+      <View style={{ height: '100%' }}>
         <View
           style={{
-            maxWidth: '100%',
-            width: 900,
-            height: 550
+            flexDirection: 'row',
+            alignItems: 'center',
+            padding: '0 10px 5px'
           }}
         >
+          <Component initialState={{ menuOpen: false }}>
+            {({ state, setState }) => (
+              <View>
+                <Button
+                  bare
+                  style={{ marginRight: 10 }}
+                  disabled={buttonsDisabled}
+                  onClick={() => setState({ menuOpen: true })}
+                >
+                  {buttonsDisabled
+                    ? 'No payees selected'
+                    : selected.items.size +
+                      ' ' +
+                      plural(selected.items.size, 'payee', 'payees')}
+                  <ExpandArrow width={8} height={8} style={{ marginLeft: 5 }} />
+                </Button>
+                {state.menuOpen && (
+                  <PayeeMenu
+                    payeesById={payeesById}
+                    selectedPayees={selected.items}
+                    onClose={() => setState({ menuOpen: false })}
+                    onDelete={onDelete}
+                    onMerge={onMerge}
+                  />
+                )}
+              </View>
+            )}
+          </Component>
+          <View style={{ flex: 1 }} />
+          <Input
+            placeholder="Filter payees..."
+            value={filter}
+            onChange={e => {
+              applyFilter(e.target.value);
+              tableNavigator.onEdit(null);
+            }}
+            style={{
+              width: 350,
+              borderColor: 'transparent',
+              backgroundColor: colors.n11,
+              ':focus': {
+                backgroundColor: 'white',
+                '::placeholder': { color: colors.n8 }
+              }
+            }}
+          />
+        </View>
+
+        <SelectedProvider instance={selected} fetchAllIds={getSelectableIds}>
           <View
             style={{
-              flexDirection: 'row',
-              alignItems: 'center',
-              padding: '0 10px'
+              flex: 1,
+              border: '1px solid ' + colors.border,
+              borderRadius: 4,
+              overflow: 'hidden'
             }}
           >
-            <Component initialState={{ menuOpen: false }}>
-              {({ state, setState }) => (
-                <View>
-                  <Button
-                    bare
-                    style={{ marginRight: 10 }}
-                    disabled={buttonsDisabled}
-                    onClick={() => setState({ menuOpen: true })}
-                  >
-                    {buttonsDisabled
-                      ? 'No payees selected'
-                      : selected.items.size +
-                        ' ' +
-                        plural(selected.items.size, 'payee', 'payees')}
-                    <ExpandArrow
-                      width={8}
-                      height={8}
-                      style={{ marginLeft: 5 }}
-                    />
-                  </Button>
-                  {state.menuOpen && (
-                    <PayeeMenu
-                      payeesById={payeesById}
-                      selectedPayees={selected.items}
-                      onClose={() => setState({ menuOpen: false })}
-                      onDelete={onDelete}
-                      onMerge={onMerge}
-                    />
-                  )}
-                </View>
-              )}
-            </Component>
-            <View style={{ flex: 1 }} />
-            <Input
-              placeholder="Filter payees..."
-              value={filter}
-              onChange={e => {
-                applyFilter(e.target.value);
-                tableNavigator.onEdit(null);
-              }}
-              style={{
-                width: 350,
-                borderColor: 'transparent',
-                backgroundColor: colors.n11,
-                ':focus': {
-                  backgroundColor: 'white',
-                  '::placeholder': { color: colors.n8 }
-                }
-              }}
-            />
+            <PayeeTableHeader />
+            {filteredPayees.length === 0 ? (
+              <EmptyMessage text="No payees" style={{ marginTop: 15 }} />
+            ) : (
+              <PayeeTable
+                ref={table}
+                payees={filteredPayees}
+                ruleCounts={ruleCounts}
+                categoryGroups={categoryGroups}
+                highlightedRows={highlightedRows}
+                navigator={tableNavigator}
+                onUpdate={onUpdate}
+                onViewRules={onViewRules}
+                onCreateRule={onCreateRule}
+              />
+            )}
           </View>
-
-          <SelectedProvider instance={selected} fetchAllIds={getSelectableIds}>
-            <View
-              style={{
-                flex: 1,
-                border: '1px solid ' + colors.border,
-                borderRadius: 4,
-                overflow: 'hidden',
-                margin: 5
-              }}
-            >
-              <PayeeTableHeader />
-              {filteredPayees.length === 0 ? (
-                <EmptyMessage text="No payees" style={{ marginTop: 15 }} />
-              ) : (
-                <PayeeTable
-                  ref={table}
-                  payees={filteredPayees}
-                  ruleCounts={ruleCounts}
-                  categoryGroups={categoryGroups}
-                  highlightedRows={highlightedRows}
-                  navigator={tableNavigator}
-                  onUpdate={onUpdate}
-                  onViewRules={onViewRules}
-                  onCreateRule={onCreateRule}
-                />
-              )}
-            </View>
-          </SelectedProvider>
-        </View>
-      </Modal>
+        </SelectedProvider>
+      </View>
     );
   }
 );
diff --git a/packages/loot-design/src/components/sidebar.js b/packages/loot-design/src/components/sidebar.js
index 3015ea5f5..0ef9e193e 100644
--- a/packages/loot-design/src/components/sidebar.js
+++ b/packages/loot-design/src/components/sidebar.js
@@ -374,9 +374,6 @@ const MenuButton = withRouter(function MenuButton({ history }) {
     setMenuOpen(false);
 
     switch (type) {
-      case 'open-payees':
-        dispatch(pushModal('manage-payees'));
-        break;
       case 'find-schedules':
         history.push('/schedule/discover', { locationPtr: history.location });
         break;
@@ -394,7 +391,6 @@ const MenuButton = withRouter(function MenuButton({ history }) {
   }
 
   let items = [
-    { name: 'open-payees', text: 'Manage Payees' },
     { name: 'find-schedules', text: 'Find schedules' },
     { name: 'repair-splits', text: 'Repair split transactions' },
     Menu.line,
@@ -438,7 +434,7 @@ function Tools() {
 
   useEffect(() => {
     if (
-      ['/schedules', '/rules'].some(route =>
+      ['/schedules', '/payees', '/rules'].some(route =>
         location.pathname.startsWith(route)
       )
     ) {
@@ -488,6 +484,17 @@ function Tools() {
             }
             to="/schedules"
           />
+          <Item
+            title="Payees"
+            icon={
+              <StoreFrontIcon
+                width={15}
+                height={15}
+                style={{ color: 'inherit' }}
+              />
+            }
+            to="/payees"
+          />
           <Item
             title="Rules"
             icon={
-- 
GitLab