diff --git a/components/transactions/Transactions.js b/components/transactions/Transactions.js
deleted file mode 100644
index 12cbec7d1b7..00000000000
--- a/components/transactions/Transactions.js
+++ /dev/null
@@ -1,278 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { useQuery } from '@apollo/react-hooks';
-import { mapValues } from 'lodash';
-import { useRouter } from 'next/router';
-import { FormattedMessage } from 'react-intl';
-
-import { getErrorFromGraphqlException } from '../../lib/errors';
-import { API_V2_CONTEXT, gqlV2 } from '../../lib/graphql/helpers';
-import { Router } from '../../server/pages';
-
-import { parseAmountRange } from '../expenses/filters/ExpensesAmountFilter';
-import { getDateRangeFromPeriod } from '../expenses/filters/ExpensesDateFilter';
-import { Box, Flex } from '../Grid';
-import Link from '../Link';
-import MessageBox from '../MessageBox';
-import Pagination from '../Pagination';
-import SearchBar from '../SearchBar';
-import StyledHr from '../StyledHr';
-import { H1 } from '../Text';
-
-import TransactionsDownloadCSV from './TransactionsDownloadCSV';
-import TransactionsDownloadInvoices from './TransactionsDownloadInvoices';
-import TransactionsFilters from './TransactionsFilters';
-import TransactionsList from './TransactionsList';
-
-const transactionsQuery = gqlV2/* GraphQL */ `
- query Transactions(
- $slug: String!
- $limit: Int!
- $offset: Int!
- $type: TransactionType
- $minAmount: Int
- $maxAmount: Int
- $dateFrom: ISODateTime
- $searchTerm: String
- ) {
- transactions(
- account: { slug: $slug }
- limit: $limit
- offset: $offset
- type: $type
- minAmount: $minAmount
- maxAmount: $maxAmount
- dateFrom: $dateFrom
- searchTerm: $searchTerm
- ) {
- totalCount
- offset
- limit
- nodes {
- id
- uuid
- amount {
- currency
- valueInCents
- }
- netAmount {
- currency
- valueInCents
- }
- platformFee {
- currency
- valueInCents
- }
- paymentProcessorFee {
- currency
- valueInCents
- }
- hostFee {
- currency
- valueInCents
- }
- type
- description
- createdAt
- isRefunded
- toAccount {
- id
- name
- slug
- type
- imageUrl
- ... on Collective {
- host {
- name
- slug
- type
- }
- }
- }
- fromAccount {
- id
- name
- slug
- type
- imageUrl
- }
- paymentMethod {
- type
- }
- order {
- id
- status
- }
- expense {
- id
- status
- tags
- type
- legacyId
- comments {
- totalCount
- }
- payoutMethod {
- type
- }
- account {
- slug
- }
- createdByAccount {
- slug
- }
- }
- }
- }
- }
-`;
-
-const EXPENSES_PER_PAGE = 15;
-
-const getVariablesFromQuery = query => {
- const amountRange = parseAmountRange(query.amount);
- const [dateFrom] = getDateRangeFromPeriod(query.period);
- return {
- offset: parseInt(query.offset) || 0,
- limit: parseInt(query.limit) || EXPENSES_PER_PAGE,
- type: query.type,
- status: query.status,
- tags: query.tag ? [query.tag] : undefined,
- minAmount: amountRange[0] && amountRange[0] * 100,
- maxAmount: amountRange[1] && amountRange[1] * 100,
- payoutMethodType: query.payout,
- dateFrom,
- searchTerm: query.searchTerm,
- };
-};
-
-const Transactions = ({ collective, LoggedInUser }) => {
- const { query } = useRouter() || {};
- const { data, error, loading, variables } = useQuery(transactionsQuery, {
- variables: { slug: collective.slug, ...getVariablesFromQuery(query) },
- context: API_V2_CONTEXT,
- });
- const hasFilters = React.useMemo(
- () =>
- Object.entries(query).some(([key, value]) => {
- return !['view', 'offset', 'limit', 'slug'].includes(key) && value;
- }),
- [query],
- );
-
- const isHostAdmin = LoggedInUser?.isHostAdmin(collective);
- const isCollectiveAdmin = LoggedInUser?.canEditCollective(collective);
- const canDownloadInvoices =
- isHostAdmin || (isCollectiveAdmin && (collective.type === 'ORGANIZATION' || collective.type === 'USER'));
-
- return (
-
-
-
-
-
-
- Router.pushRoute('transactions', { ...query, searchTerm, offset: null })}
- />
-
-
-
-
-
- Router.pushRoute('transactions', {
- ...query,
- ...queryParams,
- offset: null,
- })
- }
- />
-
- {canDownloadInvoices && (
-
-
-
- )}
-
-
-
- {error ? (
-
- {getErrorFromGraphqlException(error).message}
-
- ) : !loading && !data.transactions?.nodes.length ? (
-
- {hasFilters ? (
- null),
- collectiveSlug: collective.slug,
- view: 'transactions',
- }}
- >
- {text}
-
- );
- },
- }}
- />
- ) : (
-
- )}
-
- ) : (
-
-
-
-
-
-
- )}
-
- );
-};
-
-Transactions.propTypes = {
- /** Collective */
- collective: PropTypes.shape({
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- slug: PropTypes.string.isRequired,
- type: PropTypes.string.isRequired,
- currency: PropTypes.string.isRequired,
- platformFeePercent: PropTypes.number,
- }).isRequired,
- /** @ignore from injectIntl */
- intl: PropTypes.object,
- LoggedInUser: PropTypes.object,
-};
-
-export default Transactions;
diff --git a/pages/transactions.js b/pages/transactions.js
index bddb00990f2..b350a172e51 100644
--- a/pages/transactions.js
+++ b/pages/transactions.js
@@ -1,23 +1,143 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { get } from 'lodash';
+import { graphql } from '@apollo/react-hoc';
+import { get, mapValues } from 'lodash';
+import { FormattedMessage } from 'react-intl';
import styled from 'styled-components';
import { CollectiveType } from '../lib/constants/collectives';
+import { getErrorFromGraphqlException } from '../lib/errors';
+import { API_V2_CONTEXT, gqlV2 } from '../lib/graphql/helpers';
import { addCollectiveCoverData } from '../lib/graphql/queries';
+import { Router } from '../server/pages';
import Body from '../components/Body';
import { Sections } from '../components/collective-page/_constants';
import CollectiveNavbar from '../components/CollectiveNavbar';
import Container from '../components/Container';
import ErrorPage from '../components/ErrorPage';
+import { parseAmountRange } from '../components/expenses/filters/ExpensesAmountFilter';
+import { getDateRangeFromPeriod } from '../components/expenses/filters/ExpensesDateFilter';
import Footer from '../components/Footer';
+import { Box, Flex } from '../components/Grid';
import Header from '../components/Header';
+import Link from '../components/Link';
import Loading from '../components/Loading';
+import MessageBox from '../components/MessageBox';
import Page from '../components/Page';
-import Transactions from '../components/transactions/Transactions';
+import Pagination from '../components/Pagination';
+import SearchBar from '../components/SearchBar';
+import StyledHr from '../components/StyledHr';
+import { H1 } from '../components/Text';
+import TransactionsDownloadCSV from '../components/transactions/TransactionsDownloadCSV';
+import TransactionsDownloadInvoices from '../components/transactions/TransactionsDownloadInvoices';
+import TransactionsFilters from '../components/transactions/TransactionsFilters';
+import TransactionsList from '../components/transactions/TransactionsList';
import { withUser } from '../components/UserProvider';
+const transactionsQuery = gqlV2/* GraphQL */ `
+ query Transactions(
+ $slug: String!
+ $limit: Int!
+ $offset: Int!
+ $type: TransactionType
+ $minAmount: Int
+ $maxAmount: Int
+ $dateFrom: ISODateTime
+ $searchTerm: String
+ ) {
+ transactions(
+ account: { slug: $slug }
+ limit: $limit
+ offset: $offset
+ type: $type
+ minAmount: $minAmount
+ maxAmount: $maxAmount
+ dateFrom: $dateFrom
+ searchTerm: $searchTerm
+ ) {
+ totalCount
+ offset
+ limit
+ nodes {
+ id
+ uuid
+ amount {
+ currency
+ valueInCents
+ }
+ netAmount {
+ currency
+ valueInCents
+ }
+ platformFee {
+ currency
+ valueInCents
+ }
+ paymentProcessorFee {
+ currency
+ valueInCents
+ }
+ hostFee {
+ currency
+ valueInCents
+ }
+ type
+ description
+ createdAt
+ isRefunded
+ toAccount {
+ id
+ name
+ slug
+ type
+ imageUrl
+ ... on Collective {
+ host {
+ name
+ slug
+ type
+ }
+ }
+ }
+ fromAccount {
+ id
+ name
+ slug
+ type
+ imageUrl
+ }
+ paymentMethod {
+ type
+ }
+ order {
+ id
+ status
+ }
+ expense {
+ id
+ status
+ tags
+ type
+ legacyId
+ comments {
+ totalCount
+ }
+ payoutMethod {
+ type
+ }
+ account {
+ slug
+ }
+ createdByAccount {
+ slug
+ }
+ }
+ }
+ }
+ }
+`;
+
const TransactionPageWrapper = styled.div`
display: flex;
flex-direction: column;
@@ -27,15 +147,36 @@ const TransactionPageWrapper = styled.div`
}
`;
+const EXPENSES_PER_PAGE = 15;
+
+const getVariablesFromQuery = query => {
+ const amountRange = parseAmountRange(query.amount);
+ const [dateFrom] = getDateRangeFromPeriod(query.period);
+ return {
+ offset: parseInt(query.offset) || 0,
+ limit: parseInt(query.limit) || EXPENSES_PER_PAGE,
+ type: query.type,
+ status: query.status,
+ tags: query.tag ? [query.tag] : undefined,
+ minAmount: amountRange[0] && amountRange[0] * 100,
+ maxAmount: amountRange[1] && amountRange[1] * 100,
+ payoutMethodType: query.payout,
+ dateFrom,
+ searchTerm: query.searchTerm,
+ };
+};
+
class TransactionsPage extends React.Component {
- static getInitialProps({ query: { collectiveSlug } }) {
- return { slug: collectiveSlug };
+ static async getInitialProps({ query: { collectiveSlug, ...query } }) {
+ return { slug: collectiveSlug, query };
}
static propTypes = {
slug: PropTypes.string, // from getInitialProps, for addCollectiveCoverData
data: PropTypes.object.isRequired, // from withData
+ transactionsData: PropTypes.object,
LoggedInUser: PropTypes.object,
+ query: PropTypes.object,
};
constructor(props) {
@@ -61,17 +202,24 @@ class TransactionsPage extends React.Component {
}
render() {
- const { LoggedInUser } = this.props;
+ const { LoggedInUser, query, transactionsData, data, slug } = this.props;
const collective = get(this.props, 'data.Collective') || this.state.Collective;
+ const { transactions, error, loading, variables } = transactionsData;
+ const hasFilters = Object.entries(query).some(([key, value]) => {
+ return !['view', 'offset', 'limit', 'slug'].includes(key) && value;
+ });
+ const canDownloadInvoices =
+ (LoggedInUser?.isHostAdmin(collective) || LoggedInUser?.canEditCollective(collective)) &&
+ (collective.type === 'ORGANIZATION' || collective.type === 'USER');
- if (!collective && this.props.data.loading) {
+ if (!collective && data.loading) {
return (
);
} else if (!collective) {
- return ;
+ return ;
}
return (
@@ -90,14 +238,98 @@ class TransactionsPage extends React.Component {
}}
/>
-
-
+
+
+
+
+
+
+ Router.pushRoute('transactions', { ...query, searchTerm, offset: null })}
+ />
+
+
+
+
+
+ Router.pushRoute('transactions', {
+ ...query,
+ ...queryParams,
+ collectiveSlug: slug,
+ offset: null,
+ })
+ }
+ />
+
+ {canDownloadInvoices && (
+
+
+
+ )}
+
+
+
+ {error ? (
+
+ {getErrorFromGraphqlException(error).message}
+
+ ) : !loading && !transactions?.nodes?.length ? (
+
+ {hasFilters ? (
+ null),
+ collectiveSlug: collective.slug,
+ view: 'transactions',
+ }}
+ >
+ {text}
+
+ );
+ },
+ }}
+ />
+ ) : (
+
+ )}
+
+ ) : (
+
+
+
+
+
+
+ )}
+