monopyly 1.4.1__tar.gz → 1.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {monopyly-1.4.1 → monopyly-1.4.3}/.gitignore +2 -1
- {monopyly-1.4.1 → monopyly-1.4.3}/PKG-INFO +6 -5
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/README.md +2 -2
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/__init__.py +0 -5
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/_version.py +2 -2
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/auth/routes.py +3 -1
- monopyly-1.4.3/monopyly/cli/apps.py +84 -0
- monopyly-1.4.3/monopyly/cli/run.py +122 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/config/default_settings.py +21 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/config/settings.py +12 -1
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/core/routes.py +1 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/database/__init__.py +1 -1
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/css/style.css +3 -1
- monopyly-1.4.3/monopyly/static/jquery-3.7.0.min.js +3 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/define-filter.js +2 -2
- monopyly-1.4.3/monopyly/static/js/expand-transaction.js +18 -0
- monopyly-1.4.3/monopyly/static/js/modules/expand-transaction.js +128 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/update-display-ajax.js +15 -8
- monopyly-1.4.3/monopyly/static/js/update-transactions-display.js +73 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/pyproject.toml +4 -3
- monopyly-1.4.1/monopyly/cli/run.py +0 -107
- monopyly-1.4.1/monopyly/static/jquery-3.7.0.min.js +0 -2
- monopyly-1.4.1/monopyly/static/js/expand-transaction.js +0 -32
- monopyly-1.4.1/monopyly/static/js/modules/expand-transaction.js +0 -63
- monopyly-1.4.1/monopyly/static/js/update-transactions-display.js +0 -66
- {monopyly-1.4.1 → monopyly-1.4.3}/COPYING +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/LICENSE +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/README.md +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/auth/actions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/auth/blueprint.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/auth/tools.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/accounts.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/actions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/banks.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/blueprint.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/filters.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/forms.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/routes.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/banking/transactions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/common/forms/__init__.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/common/forms/_forms.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/common/forms/fields.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/common/forms/utils.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/common/forms/validators.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/common/transactions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/common/utils.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/config/__init__.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/core/actions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/core/blueprint.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/core/context_processors.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/core/filters.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/core/internal_transactions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/accounts.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/actions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/blueprint.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/cards.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/forms.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/routes.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/statements.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/transactions/__init__.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/credit/transactions/_transactions.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/database/models.py +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/database/preloads.sql +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/database/schema.sql +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/database/views.sql +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/browserconfig.xml +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-114.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-120.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-144.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-150.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-152.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-16.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-160.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-180.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-192.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-310.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-32.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-57.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-60.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-64.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-70.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-72.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-76.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon-96.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon.ico +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/favicon/favicon.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/bank-account-details.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/bank-account-summaries.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/bank-accounts.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/credit-account-details.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/credit-transactions.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/homepage-user.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/homepage.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/about/statement-details.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/cards/chase-card.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/cards/discover-card.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/cards/new-card.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/cards/template-card.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/arrow-down.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/arrow-left.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/arrow-up.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/checkmark.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/delete-orange-thick.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/delete-orange.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/delete-thick.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/delete.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/edit.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/link.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/minus-thick.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/minus.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/plus-thick.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/plus.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/refresh.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/save.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/sort-asc.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/sort-desc.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/statement-pair.svg +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/statement.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/statement.svg +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/icons/x-thick.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/img/statement.png +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/add-subtransaction.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/add-transfer.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/autocomplete-transaction.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/bind-tag-actions.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/create-balance-chart.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/display-new-account-type-inputs.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/display-new-bank-inputs.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/display-new-credit-account-inputs.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/expand-bank-account.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/expand-bank.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/flip-card.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/hide-homepage-block.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/infer-card.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/infer-statement.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/make-payment.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/ajax.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/autocomplete-input.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/expand-box-row.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/manage-acquisition-form.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/manage-overlays.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/manage-subforms.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/modules/update-database-widget.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/show-linked-transaction.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/update-account-statement-parameters.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/update-bank-name.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/update-card-status.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/update-statement-parameters.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/static/js/update-statements-display.js +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/auth/login.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/auth/register.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/account_form/account_form.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/account_form/account_form_page_new.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/account_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/account_summaries.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/account_summaries_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/account_summary.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/accounts_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transaction_form/bank_info_form.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transaction_form/transaction_form.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transaction_form/transaction_form_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transaction_form/transaction_form_page_new.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transaction_form/transaction_form_page_update.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transaction_form/transfer_form.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transactions_table/condensed_row_content.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transactions_table/expanded_row_content.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transactions_table/transaction_field_titles.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/banking/transactions_table/transactions.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/form_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transaction_form/subform.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transaction_form/subtransaction_subform.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transaction_form/transaction_form_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transactions_table/linked_bank_transaction.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transactions_table/linked_credit_transaction.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transactions_table/linked_transaction_overlay.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transactions_table/subtransactions.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transactions_table/transaction_condensed.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transactions_table/transaction_expanded.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/common/transactions_table/transactions.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/account_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/card_form/card_form.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/card_form/card_form_page_new.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/card_form/transfer_statement_inquiry.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/card_graphic/card_back.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/card_graphic/card_front.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/card_submission_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/cards.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/cards_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/statement_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/statement_summary.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/statements.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/statements_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/tag_tree/subtag_tree.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/tag_tree/tag_tree.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/tags_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transaction_form/transaction_form.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transaction_form/transaction_form_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transaction_form/transaction_form_page_new.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transaction_form/transaction_form_page_update.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transaction_submission_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transactions_page.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transactions_table/condensed_row_content.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transactions_table/expanded_row_content.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transactions_table/transaction_field_titles.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credit/transactions_table/transactions.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/credits.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/index.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/layout.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/profile.html +0 -0
- {monopyly-1.4.1 → monopyly-1.4.3}/monopyly/templates/story.html +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: monopyly
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.3
|
|
4
4
|
Summary: A homemade personal finance manager.
|
|
5
5
|
Project-URL: Download, https://pypi.org/project/monopyly
|
|
6
|
-
Project-URL: Homepage,
|
|
6
|
+
Project-URL: Homepage, http://monopyly.com
|
|
7
7
|
Project-URL: Repository, https://github.com/mitchnegus/monopyly
|
|
8
8
|
Project-URL: Changelog, https://github.com/mitchnegus/monopyly/blob/main/CHANGELOG.md
|
|
9
9
|
Author-email: Mitch Negus <mitchnegus57@gmail.com>
|
|
@@ -22,11 +22,12 @@ Classifier: Programming Language :: Python
|
|
|
22
22
|
Classifier: Topic :: Office/Business :: Financial
|
|
23
23
|
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
24
24
|
Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
|
|
25
|
-
Requires-Python: <3.11,>=3.
|
|
25
|
+
Requires-Python: <3.11,>=3.10
|
|
26
26
|
Requires-Dist: authanor>=1.0.2
|
|
27
27
|
Requires-Dist: flask-wtf
|
|
28
28
|
Requires-Dist: flask>=2.2.2
|
|
29
29
|
Requires-Dist: fuisce>1.0.0
|
|
30
|
+
Requires-Dist: gunicorn>=21.2.0
|
|
30
31
|
Requires-Dist: markdown>=3.4.3
|
|
31
32
|
Requires-Dist: python-dateutil
|
|
32
33
|
Requires-Dist: sqlalchemy>=2.0.0
|
|
@@ -64,10 +65,10 @@ The package requires a recent version of Python (3.9+).
|
|
|
64
65
|
Once the package is properly installed, run the app from the command line (the default options should be sensible, but you may customize the host and port if necessary):
|
|
65
66
|
|
|
66
67
|
```
|
|
67
|
-
$ monopyly
|
|
68
|
+
$ monopyly development --browser [--host HOST] [--port PORT]
|
|
68
69
|
```
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
By using the `--browser` option in development mode, this will open to an empty homepage with a welcome message.
|
|
71
72
|
|
|
72
73
|
<img class="screenshot" src="https://raw.githubusercontent.com/mitchnegus/monopyly/main/monopyly/static/img/about/homepage.png" alt="user homepage" width="800px">
|
|
73
74
|
|
|
@@ -30,10 +30,10 @@ The package requires a recent version of Python (3.9+).
|
|
|
30
30
|
Once the package is properly installed, run the app from the command line (the default options should be sensible, but you may customize the host and port if necessary):
|
|
31
31
|
|
|
32
32
|
```
|
|
33
|
-
$ monopyly
|
|
33
|
+
$ monopyly development --browser [--host HOST] [--port PORT]
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
By using the `--browser` option in development mode, this will open to an empty homepage with a welcome message.
|
|
37
37
|
|
|
38
38
|
<img class="screenshot" src="monopyly/static/img/about/homepage.png" alt="user homepage" width="800px">
|
|
39
39
|
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Run a development server for the Monopyly app.
|
|
3
3
|
"""
|
|
4
|
-
import warnings
|
|
5
|
-
|
|
6
4
|
from flask import Flask
|
|
7
5
|
|
|
8
6
|
from monopyly.config import DevelopmentConfig, ProductionConfig
|
|
@@ -22,9 +20,6 @@ def create_app(test_config=None):
|
|
|
22
20
|
config = DevelopmentConfig.configure_for_instance(app.instance_path)
|
|
23
21
|
else:
|
|
24
22
|
config = ProductionConfig.configure_for_instance(app.instance_path)
|
|
25
|
-
# Give an alert while the secret key remains insecure
|
|
26
|
-
warnings.formatwarning = lambda msg, *args, **kwargs: f"\n{msg}\n"
|
|
27
|
-
warnings.warn("INSECURE: Production mode has not yet been fully configured")
|
|
28
23
|
app.config.from_object(config)
|
|
29
24
|
|
|
30
25
|
# Initialize the app, including CLI commands and blueprints
|
|
@@ -26,7 +26,9 @@ def register():
|
|
|
26
26
|
# Get username and passwords from the form
|
|
27
27
|
username, password = get_username_and_password(request.form)
|
|
28
28
|
# Check for errors in the accessed information
|
|
29
|
-
if not
|
|
29
|
+
if not current_app.config["REGISTRATION"]:
|
|
30
|
+
error = "The app is not currently accepting new registrations."
|
|
31
|
+
elif not username:
|
|
30
32
|
error = "Username is required."
|
|
31
33
|
elif not password:
|
|
32
34
|
error = "Password is required."
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Application objects for running the app via the CLI."""
|
|
2
|
+
import multiprocessing
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from gunicorn.app.base import BaseApplication
|
|
6
|
+
|
|
7
|
+
from .. import create_app
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LocalApplication:
|
|
11
|
+
"""An object for running the application locally."""
|
|
12
|
+
|
|
13
|
+
default_port = "5001"
|
|
14
|
+
command = ["flask"]
|
|
15
|
+
|
|
16
|
+
def __init__(self, host=None, port=None, **options):
|
|
17
|
+
"""Initialize the application in development mode."""
|
|
18
|
+
self._host = host
|
|
19
|
+
self._port = port
|
|
20
|
+
if options:
|
|
21
|
+
raise NotImplementedError(
|
|
22
|
+
"Options besides `host` and `port` are not handled in development mode."
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def run(self):
|
|
26
|
+
"""Run the Monopyly application in development mode."""
|
|
27
|
+
instruction = self.command + ["run"]
|
|
28
|
+
if self._host:
|
|
29
|
+
instruction += ["--host", self._host]
|
|
30
|
+
if self._port:
|
|
31
|
+
instruction += ["--port", self._port]
|
|
32
|
+
server = subprocess.Popen(instruction)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DevelopmentApplication(LocalApplication):
|
|
36
|
+
"""An object for running the application in development mode."""
|
|
37
|
+
|
|
38
|
+
default_port = "5000"
|
|
39
|
+
command = LocalApplication.command + ["--debug"]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ProductionApplication(BaseApplication):
|
|
43
|
+
"""An object for running the application in production mode (via Gunicorn)."""
|
|
44
|
+
|
|
45
|
+
default_port = "8000"
|
|
46
|
+
_default_worker_count = (multiprocessing.cpu_count() * 2) + 1
|
|
47
|
+
|
|
48
|
+
def __init__(self, host=None, port=None, **options):
|
|
49
|
+
"""Initialize the application in production mode."""
|
|
50
|
+
options["bind"] = self._parse_binding(host, port, options.get("bind"))
|
|
51
|
+
options.setdefault("workers", self._default_worker_count)
|
|
52
|
+
self.options = options
|
|
53
|
+
self.application = create_app()
|
|
54
|
+
super().__init__()
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def _parse_binding(host, port, bind_option):
|
|
58
|
+
# Parse any socket binding options
|
|
59
|
+
if (host or port) and bind_option:
|
|
60
|
+
raise ValueError(
|
|
61
|
+
"Neither `host` nor `port` parameters can be specified if the "
|
|
62
|
+
"`bind` option is given."
|
|
63
|
+
)
|
|
64
|
+
bind_values = []
|
|
65
|
+
if host:
|
|
66
|
+
bind_values.append(host)
|
|
67
|
+
if port:
|
|
68
|
+
bind_values.append(port)
|
|
69
|
+
return bind if (bind := ":".join(bind_values)) else bind_option
|
|
70
|
+
|
|
71
|
+
def load_config(self):
|
|
72
|
+
config = {
|
|
73
|
+
key: value
|
|
74
|
+
for key, value in self.options.items()
|
|
75
|
+
if key in self.cfg.settings and value is not None
|
|
76
|
+
}
|
|
77
|
+
for key, value in config.items():
|
|
78
|
+
self.cfg.set(key.lower(), value)
|
|
79
|
+
|
|
80
|
+
def load(self):
|
|
81
|
+
return self.application
|
|
82
|
+
|
|
83
|
+
def run(self, *args, **kwargs):
|
|
84
|
+
return super().run(*args, **kwargs)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
A script (entry point) to launch the Monopyly application.
|
|
4
|
+
"""
|
|
5
|
+
import argparse
|
|
6
|
+
import os
|
|
7
|
+
import signal
|
|
8
|
+
import subprocess
|
|
9
|
+
import time
|
|
10
|
+
import webbrowser
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from threading import Event
|
|
13
|
+
|
|
14
|
+
from flask import current_app
|
|
15
|
+
from rich.console import Console
|
|
16
|
+
|
|
17
|
+
from .apps import DevelopmentApplication, LocalApplication, ProductionApplication
|
|
18
|
+
|
|
19
|
+
# Set the Flask environment variable
|
|
20
|
+
os.environ["FLASK_APP"] = "monopyly"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
args = parse_arguments()
|
|
25
|
+
app_launcher = Launcher(args.mode, host=args.host, port=args.port)
|
|
26
|
+
# Initialize the database and run the app
|
|
27
|
+
app_launcher.initialize_database()
|
|
28
|
+
if args.backup:
|
|
29
|
+
app_launcher.backup_database()
|
|
30
|
+
app_launcher.launch()
|
|
31
|
+
if args.mode in ("development", "local"):
|
|
32
|
+
# Enable browser viewing in development mode
|
|
33
|
+
if args.browser:
|
|
34
|
+
app_launcher.open_browser(delay=1)
|
|
35
|
+
# Wait for the exit command to stop
|
|
36
|
+
app_launcher.wait_for_exit()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def parse_arguments():
|
|
40
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
41
|
+
parser.add_argument("--host", help="the host address where the app will be run")
|
|
42
|
+
parser.add_argument("--port", help="the port where the app will be accessible")
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"--backup",
|
|
45
|
+
action="store_true",
|
|
46
|
+
help="a flag indicating if the database should be backed up",
|
|
47
|
+
)
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--browser",
|
|
50
|
+
action="store_true",
|
|
51
|
+
help=(
|
|
52
|
+
"a flag indicating if a new browser window should be opened (development "
|
|
53
|
+
"and local modes only)"
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"mode",
|
|
58
|
+
help="the runtime mode for the app",
|
|
59
|
+
choices=["development", "local", "production"],
|
|
60
|
+
)
|
|
61
|
+
return parser.parse_args()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Launcher:
|
|
65
|
+
"""A tool to build and execute Flask commands."""
|
|
66
|
+
|
|
67
|
+
_application_types = {
|
|
68
|
+
"development": DevelopmentApplication,
|
|
69
|
+
"local": LocalApplication,
|
|
70
|
+
"production": ProductionApplication,
|
|
71
|
+
}
|
|
72
|
+
_console = Console()
|
|
73
|
+
_exit = Event()
|
|
74
|
+
command = ["flask"]
|
|
75
|
+
|
|
76
|
+
def __init__(self, mode, host=None, port=None):
|
|
77
|
+
app_type = self._application_types[mode]
|
|
78
|
+
self.host = host if host else "127.0.0.1"
|
|
79
|
+
self.port = port if port else app_type.default_port
|
|
80
|
+
self.app = app_type(host=self.host, port=self.port)
|
|
81
|
+
|
|
82
|
+
def initialize_database(self):
|
|
83
|
+
"""Run the database initializer."""
|
|
84
|
+
instruction = self.command + ["init-db"]
|
|
85
|
+
self._console.print("[deep_sky_blue1]Initializing the database...")
|
|
86
|
+
subprocess.run(instruction)
|
|
87
|
+
print("\n")
|
|
88
|
+
|
|
89
|
+
def backup_database(self):
|
|
90
|
+
"""Back up the app database."""
|
|
91
|
+
self._console.print("[deep_sky_blue1]Backing up the database...")
|
|
92
|
+
instruction = self.command + ["back-up-db"]
|
|
93
|
+
subprocess.run(instruction)
|
|
94
|
+
print("\n")
|
|
95
|
+
|
|
96
|
+
def launch(self):
|
|
97
|
+
"""Launch the Monopyly application."""
|
|
98
|
+
self._console.print("[deep_sky_blue1]Running the Monopyly application...\n")
|
|
99
|
+
self.app.run()
|
|
100
|
+
|
|
101
|
+
def open_browser(self, delay=0):
|
|
102
|
+
"""Open the default web browser."""
|
|
103
|
+
time.sleep(delay)
|
|
104
|
+
webbrowser.open(f"http://{self.host}:{self.port}/")
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def wait_for_exit(cls):
|
|
108
|
+
"""Wait for the exit command (e.g., keyboard interrupt) to be issued."""
|
|
109
|
+
for sig in ("TERM", "HUP", "INT"):
|
|
110
|
+
signal.signal(getattr(signal, "SIG" + sig), cls._quit)
|
|
111
|
+
while not cls._exit.is_set():
|
|
112
|
+
cls._exit.wait(1)
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def _quit(cls, signo, _frame):
|
|
116
|
+
"""Send the signal to quit the app."""
|
|
117
|
+
print("\nClosing the Monopyly app...")
|
|
118
|
+
cls._exit.set()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
main()
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
"""Default configuration settings."""
|
|
2
|
+
import json
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
|
|
5
|
+
CONFIG_FILENAME = f"monopyly-config.json"
|
|
6
|
+
DEFAULT_CONFIG_PATH = Path("/etc", CONFIG_FILENAME)
|
|
7
|
+
|
|
4
8
|
|
|
5
9
|
class Config:
|
|
6
10
|
"""A base configuration object with some default settings."""
|
|
7
11
|
|
|
12
|
+
config_filepaths = [DEFAULT_CONFIG_PATH]
|
|
13
|
+
REGISTRATION = True
|
|
14
|
+
|
|
8
15
|
def __init__(self, db_path=None):
|
|
16
|
+
# Read parameters from the configuration files in order of specificity
|
|
17
|
+
for config_filepath in filter(lambda p: p.exists(), self.config_filepaths):
|
|
18
|
+
self._read_config_json(config_filepath)
|
|
9
19
|
if db_path:
|
|
10
20
|
self.DATABASE = db_path
|
|
11
21
|
|
|
@@ -18,6 +28,13 @@ class Config:
|
|
|
18
28
|
# Ensure that the database path is always set as a `pathlib.Path` object
|
|
19
29
|
self._database = Path(value)
|
|
20
30
|
|
|
31
|
+
def _read_config_json(self, config_path):
|
|
32
|
+
# Read keys and values from a configuration JSON
|
|
33
|
+
with config_path.open() as config_json:
|
|
34
|
+
config_mapping = json.load(config_json)
|
|
35
|
+
for key, value in config_mapping.items():
|
|
36
|
+
setattr(self, key, value)
|
|
37
|
+
|
|
21
38
|
|
|
22
39
|
class InstanceBasedConfig(Config):
|
|
23
40
|
"""A base configuration object for app modes using instance directories."""
|
|
@@ -30,5 +47,9 @@ class InstanceBasedConfig(Config):
|
|
|
30
47
|
"""Instantiate the app based out of the given instance directory."""
|
|
31
48
|
instance_path = Path(instance_path)
|
|
32
49
|
instance_path.mkdir(parents=True, exist_ok=True)
|
|
50
|
+
cls.config_filepaths = [
|
|
51
|
+
*super().config_filepaths,
|
|
52
|
+
instance_path / CONFIG_FILENAME,
|
|
53
|
+
]
|
|
33
54
|
db_path = Path(instance_path, cls.db_name) if cls.db_name else None
|
|
34
55
|
return cls(db_path=db_path, **kwargs)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""A module containing objects with various configuration settings."""
|
|
2
|
+
import warnings
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
|
|
4
5
|
from ..database import BASE_DB_NAME
|
|
@@ -8,9 +9,19 @@ from .default_settings import Config, InstanceBasedConfig
|
|
|
8
9
|
class ProductionConfig(InstanceBasedConfig):
|
|
9
10
|
"""A configuration object with settings for production."""
|
|
10
11
|
|
|
11
|
-
SECRET_KEY = "INSECURE
|
|
12
|
+
SECRET_KEY = "INSECURE"
|
|
12
13
|
db_name = BASE_DB_NAME
|
|
13
14
|
|
|
15
|
+
def __init__(self, db_path=None):
|
|
16
|
+
super().__init__(db_path=db_path)
|
|
17
|
+
if self.SECRET_KEY == "INSECURE":
|
|
18
|
+
# Give an alert while the secret key remains insecure
|
|
19
|
+
warnings.formatwarning = lambda msg, *args, **kwargs: f"\n{msg}\n"
|
|
20
|
+
warnings.warn(
|
|
21
|
+
"INSECURE: Production mode has not yet been fully configured; "
|
|
22
|
+
"a secret key is required."
|
|
23
|
+
)
|
|
24
|
+
|
|
14
25
|
|
|
15
26
|
class DevelopmentConfig(InstanceBasedConfig):
|
|
16
27
|
"""A configuration object with settings for development."""
|
|
@@ -252,8 +252,9 @@ aside.sidebar {
|
|
|
252
252
|
|
|
253
253
|
.screenshot {
|
|
254
254
|
width: 100%; /* override the markdown default */
|
|
255
|
+
margin: 20px 0;
|
|
255
256
|
border: 1px solid #f3f3f3;
|
|
256
|
-
box-shadow: 3px 3px
|
|
257
|
+
box-shadow: 3px 3px 5px #bbbbbb;
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
.grouping {
|
|
@@ -1207,6 +1208,7 @@ form .autocomplete-box .item.active {
|
|
|
1207
1208
|
.transactions-table .expanded .setting .date {
|
|
1208
1209
|
display: flex;
|
|
1209
1210
|
flex-direction: column;
|
|
1211
|
+
justify-content: center;
|
|
1210
1212
|
align-items: center;
|
|
1211
1213
|
flex: 2;
|
|
1212
1214
|
padding-top: 3px;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
// Identify the card filters
|
|
13
13
|
const $filterContainer = $('#card-filter');
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
// Label inactive cards when they are hovered over
|
|
16
16
|
const inactiveCardFilters = $filterContainer.find('.inactive.card');
|
|
17
17
|
let defaultText;
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
$this.text(defaultText);
|
|
32
32
|
}
|
|
33
33
|
);
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
// Change the filter status on click
|
|
36
36
|
const $filters = $filterContainer.find('.card');
|
|
37
37
|
$filters.on('click', function() {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Expand a transaction in a table when the plus icon is clicked.
|
|
3
|
+
*
|
|
4
|
+
* Expands a row in the transaction table when the plus icon offering
|
|
5
|
+
* more information is clicked. The expanded row shows transactions in
|
|
6
|
+
* more detail (and a larger font) than the rest of the transaction
|
|
7
|
+
* table. For both credit card and bank transactions, this expanded row
|
|
8
|
+
* shows subtransaction information.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
TransactionToggleManager, displaySubtransactions
|
|
13
|
+
} from './modules/expand-transaction.js';
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
(function() {
|
|
17
|
+
const toggleManager = new TransactionToggleManager(displaySubtransactions)
|
|
18
|
+
})();
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Expand a transaction when the plus icon is clicked.
|
|
3
|
+
*
|
|
4
|
+
* Expands a row in the transaction table when the plus icon offering
|
|
5
|
+
* more information is clicked. The expanded row shows transactions in
|
|
6
|
+
* more detail (and a larger font) than the rest of the transaction
|
|
7
|
+
* table. A user can exit the expanded view by clicking the 'x' icon
|
|
8
|
+
* button that is shown in the expanded view. The 'toggleTransactionRow'
|
|
9
|
+
* function takes an optional callback function which is executed after
|
|
10
|
+
* the row is expanded. The callback function receives the selected
|
|
11
|
+
* '.transaction' element as its only argument.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
replaceDisplayContentsAjaxRequest
|
|
16
|
+
} from './update-display-ajax.js';
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TransactionToggleManager {
|
|
20
|
+
/**
|
|
21
|
+
* Create the object to toggle transactions.
|
|
22
|
+
*
|
|
23
|
+
* @param {function} callback - A callback function to execute when toggling
|
|
24
|
+
* a button to get more info.
|
|
25
|
+
*/
|
|
26
|
+
constructor(callback = null) {
|
|
27
|
+
// Identify the plus/minus icons
|
|
28
|
+
this.$iconsMoreInfoButtons = $('.transaction .more.button');
|
|
29
|
+
this.$iconsLessInfoButtons = $('.transaction .less.button');
|
|
30
|
+
this.#registerClickExpand(callback);
|
|
31
|
+
this.#registerClickCollapse();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getButtonTransaction(button) {
|
|
35
|
+
return $(button).closest('.transaction');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#registerClickExpand(callback) {
|
|
39
|
+
const self = this;
|
|
40
|
+
this.$iconsMoreInfoButtons.on('click', function() {
|
|
41
|
+
const $transaction = self.getButtonTransaction(this);
|
|
42
|
+
const toggler = new TransactionToggler($transaction);
|
|
43
|
+
toggler.expand(callback);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#registerClickCollapse() {
|
|
48
|
+
const self = this;
|
|
49
|
+
this.$iconsLessInfoButtons.on('click', function() {
|
|
50
|
+
const $transaction = self.getButtonTransaction(this);
|
|
51
|
+
const toggler = new TransactionToggler($transaction);
|
|
52
|
+
toggler.collapse();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TransactionToggler {
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Create the handler.
|
|
62
|
+
*
|
|
63
|
+
* @param {Object} $transaction - The transaction to be toggled.
|
|
64
|
+
*/
|
|
65
|
+
constructor($transaction) {
|
|
66
|
+
// Set timing variables
|
|
67
|
+
this.fadeTime = 200;
|
|
68
|
+
this.slideTime = 250;
|
|
69
|
+
// Identify elements of the row
|
|
70
|
+
this.$transaction = $transaction;
|
|
71
|
+
this.$extendedRow = $transaction.find('.expanded');
|
|
72
|
+
this.$condensedRow = $transaction.find('.condensed');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Expand the transaction
|
|
77
|
+
*
|
|
78
|
+
* @param {function} callback - A callback function to execute when expanding
|
|
79
|
+
* the transaction information. The callback function takes one argument,
|
|
80
|
+
* the JQuery object representing the transaction.
|
|
81
|
+
*/
|
|
82
|
+
expand(callback = null) {
|
|
83
|
+
// Execute the callback function, if given
|
|
84
|
+
if (callback != null) {
|
|
85
|
+
callback(this.$transaction);
|
|
86
|
+
}
|
|
87
|
+
this.#toggleTransaction(this.$condensedRow, this.$extendedRow);
|
|
88
|
+
this.$transaction.addClass('selected');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
collapse($transaction) {
|
|
92
|
+
this.#toggleTransaction(this.$extendedRow, this.$condensedRow);
|
|
93
|
+
this.$transaction.removeClass('selected');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#toggleTransaction($collapser, $expander) {
|
|
97
|
+
this.#hideSummaryRow($collapser);
|
|
98
|
+
this.#showSummaryRow($expander)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
#hideSummaryRow($row) {
|
|
102
|
+
const self = this;
|
|
103
|
+
$row.fadeTo(self.fadeTime, 0, function() {
|
|
104
|
+
$(this).slideUp(self.slideTime);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#showSummaryRow($row) {
|
|
109
|
+
const self = this;
|
|
110
|
+
$row.delay(self.fadeTime).slideDown(self.slideTime, function() {
|
|
111
|
+
$(this).fadeTo(self.fadeTime, 1);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
function displaySubtransactions($transaction) {
|
|
118
|
+
|
|
119
|
+
// Execute an AJAX request to get transaction/subtransaction information
|
|
120
|
+
const endpoint = EXPAND_TRANSACTION_ENDPOINT;
|
|
121
|
+
const rawData = $transaction.data("transaction-id");
|
|
122
|
+
const $container = $transaction.find('.subtransaction-container');
|
|
123
|
+
replaceDisplayContentsAjaxRequest(endpoint, rawData, $container);
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
export { TransactionToggleManager, displaySubtransactions };
|
|
@@ -11,14 +11,21 @@
|
|
|
11
11
|
import { executeAjaxRequest } from './ajax.js';
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
function replaceDisplayContentsAjaxRequest(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
function replaceDisplayContentsAjaxRequest(
|
|
15
|
+
endpoint, rawData, $display, callback = null
|
|
16
|
+
) {
|
|
17
|
+
|
|
18
|
+
// The action is to replace the display's contents
|
|
19
|
+
function action(response) {
|
|
20
|
+
$display.html(response);
|
|
21
|
+
// Execute the callback function, if given
|
|
22
|
+
if (callback != null) {
|
|
23
|
+
callback();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Assign the response to the display object
|
|
28
|
+
executeAjaxRequest(endpoint, rawData, action);
|
|
22
29
|
|
|
23
30
|
}
|
|
24
31
|
|