Renamed summary helper to summary editor.
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| /* The Mia! Accounting Flask Project | ||||
|  * summary-helper.js: The JavaScript for the summary helper | ||||
|  * summary-editor.js: The JavaScript for the summary editor | ||||
|  */ | ||||
| 
 | ||||
| /*  Copyright (c) 2023 imacat. | ||||
| @@ -23,23 +23,23 @@ | ||||
| 
 | ||||
| // Initializes the page JavaScript.
 | ||||
| document.addEventListener("DOMContentLoaded", function () { | ||||
|     SummaryHelper.initialize(); | ||||
|     SummaryEditor.initialize(); | ||||
| }); | ||||
| 
 | ||||
| /** | ||||
|  * A summary helper. | ||||
|  * A summary editor. | ||||
|  * | ||||
|  */ | ||||
| class SummaryHelper { | ||||
| class SummaryEditor { | ||||
| 
 | ||||
|     /** | ||||
|      * The summary helper form | ||||
|      * The summary editor form | ||||
|      * @type {HTMLFormElement} | ||||
|      */ | ||||
|     #form; | ||||
| 
 | ||||
|     /** | ||||
|      * The modal of the summary helper | ||||
|      * The modal of the summary editor | ||||
|      * @type {HTMLFormElement} | ||||
|      */ | ||||
|     #modal; | ||||
| @@ -129,14 +129,14 @@ class SummaryHelper { | ||||
|     tabPlanes = {}; | ||||
| 
 | ||||
|     /** | ||||
|      * Constructs a summary helper. | ||||
|      * Constructs a summary editor. | ||||
|      * | ||||
|      * @param form {HTMLFormElement} the summary helper form | ||||
|      * @param form {HTMLFormElement} the summary editor form | ||||
|      */ | ||||
|     constructor(form) { | ||||
|         this.#form = form; | ||||
|         this.#entryType = form.dataset.entryType; | ||||
|         this.prefix = "accounting-summary-helper-" + form.dataset.entryType; | ||||
|         this.prefix = "accounting-summary-editor-" + form.dataset.entryType; | ||||
|         this.#modal = document.getElementById(this.prefix + "-modal"); | ||||
|         this.summary = document.getElementById(this.prefix + "-summary"); | ||||
|         this.number = document.getElementById(this.prefix + "-number-number"); | ||||
| @@ -156,13 +156,13 @@ class SummaryHelper { | ||||
|         } | ||||
|         this.currentTab = this.tabPlanes.general; | ||||
|         this.#initializeSuggestedAccounts(); | ||||
|         const helper = this; | ||||
|         const editor = this; | ||||
|         this.summary.onchange = function () { | ||||
|             helper.#onSummaryChange(); | ||||
|             editor.#onSummaryChange(); | ||||
|         }; | ||||
|         this.#form.onsubmit = function () { | ||||
|             if (helper.currentTab.validate()) { | ||||
|                 helper.#submit(); | ||||
|             if (editor.currentTab.validate()) { | ||||
|                 editor.#submit(); | ||||
|             } | ||||
|             return false; | ||||
|         }; | ||||
| @@ -212,10 +212,10 @@ class SummaryHelper { | ||||
|      * | ||||
|      */ | ||||
|     #initializeSuggestedAccounts() { | ||||
|         const helper = this; | ||||
|         const editor = this; | ||||
|         for (const accountButton of this.#accountButtons) { | ||||
|             accountButton.onclick = function () { | ||||
|                 helper.#selectAccount(accountButton); | ||||
|                 editor.#selectAccount(accountButton); | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| @@ -260,7 +260,7 @@ class SummaryHelper { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The callback when the summary helper is shown. | ||||
|      * The callback when the summary editor is shown. | ||||
|      * | ||||
|      */ | ||||
|     #onOpen() { | ||||
| @@ -270,7 +270,7 @@ class SummaryHelper { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Resets the summary helper. | ||||
|      * Resets the summary editor. | ||||
|      * | ||||
|      */ | ||||
|     #reset() { | ||||
| @@ -282,36 +282,36 @@ class SummaryHelper { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The summary helpers. | ||||
|      * @type {{debit: SummaryHelper, credit: SummaryHelper}} | ||||
|      * The summary editors. | ||||
|      * @type {{debit: SummaryEditor, credit: SummaryEditor}} | ||||
|      */ | ||||
|     static #helpers = {} | ||||
|     static #editors = {} | ||||
| 
 | ||||
|     /** | ||||
|      * Initializes the summary helpers. | ||||
|      * Initializes the summary editors. | ||||
|      * | ||||
|      */ | ||||
|     static initialize() { | ||||
|         const forms = Array.from(document.getElementsByClassName("accounting-summary-helper")); | ||||
|         const forms = Array.from(document.getElementsByClassName("accounting-summary-editor")); | ||||
|         const entryForm = document.getElementById("accounting-entry-form"); | ||||
|         const formSummaryControl = document.getElementById("accounting-entry-form-summary-control"); | ||||
|         for (const form of forms) { | ||||
|             const helper = new SummaryHelper(form); | ||||
|             this.#helpers[helper.#entryType] = helper; | ||||
|             const editor = new SummaryEditor(form); | ||||
|             this.#editors[editor.#entryType] = editor; | ||||
|         } | ||||
|         const helpers = this; | ||||
|         const editors = this; | ||||
|         formSummaryControl.onclick = function () { | ||||
|             helpers.#helpers[entryForm.dataset.entryType].#onOpen(); | ||||
|             editors.#editors[entryForm.dataset.entryType].#onOpen(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Initializes the summary helper for a new journal entry. | ||||
|      * Initializes the summary editor for a new journal entry. | ||||
|      * | ||||
|      * @param entryType {string} the entry type, either "debit" or "credit" | ||||
|      */ | ||||
|     static initializeNewJournalEntry(entryType) { | ||||
|         this.#helpers[entryType].#onOpen(); | ||||
|         this.#editors[entryType].#onOpen(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @@ -324,10 +324,10 @@ class SummaryHelper { | ||||
| class TabPlane { | ||||
| 
 | ||||
|     /** | ||||
|      * The parent summary helper | ||||
|      * @type {SummaryHelper} | ||||
|      * The parent summary editor | ||||
|      * @type {SummaryEditor} | ||||
|      */ | ||||
|     helper; | ||||
|     editor; | ||||
| 
 | ||||
|     /** | ||||
|      * The prefix of the HTML ID and classes | ||||
| @@ -350,11 +350,11 @@ class TabPlane { | ||||
|     /** | ||||
|      * Constructs a tab plane. | ||||
|      * | ||||
|      * @param helper {SummaryHelper} the parent summary helper | ||||
|      * @param editor {SummaryEditor} the parent summary editor | ||||
|      */ | ||||
|     constructor(helper) { | ||||
|         this.helper = helper; | ||||
|         this.prefix = this.helper.prefix + "-" + this.tabId(); | ||||
|     constructor(editor) { | ||||
|         this.editor = editor; | ||||
|         this.prefix = this.editor.prefix + "-" + this.tabId(); | ||||
|         this.#tab = document.getElementById(this.prefix + "-tab"); | ||||
|         this.#page = document.getElementById(this.prefix + "-page"); | ||||
|         const tabPlane = this; | ||||
| @@ -399,7 +399,7 @@ class TabPlane { | ||||
|      * | ||||
|      */ | ||||
|     switchToMe() { | ||||
|         for (const tabPlane of Object.values(this.helper.tabPlanes)) { | ||||
|         for (const tabPlane of Object.values(this.editor.tabPlanes)) { | ||||
|             tabPlane.#tab.classList.remove("active") | ||||
|             tabPlane.#tab.ariaCurrent = "false"; | ||||
|             tabPlane.#page.classList.add("d-none"); | ||||
| @@ -409,7 +409,7 @@ class TabPlane { | ||||
|         this.#tab.ariaCurrent = "page"; | ||||
|         this.#page.classList.remove("d-none"); | ||||
|         this.#page.ariaCurrent = "page"; | ||||
|         this.helper.currentTab = this; | ||||
|         this.editor.currentTab = this; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @@ -442,11 +442,11 @@ class TagTabPlane extends TabPlane { | ||||
|     /** | ||||
|      * Constructs a tab plane. | ||||
|      * | ||||
|      * @param helper {SummaryHelper} the parent summary helper | ||||
|      * @param editor {SummaryEditor} the parent summary editor | ||||
|      * @override | ||||
|      */ | ||||
|     constructor(helper) { | ||||
|         super(helper); | ||||
|     constructor(editor) { | ||||
|         super(editor); | ||||
|         this.tag = document.getElementById(this.prefix + "-tag"); | ||||
|         this.tagError = document.getElementById(this.prefix + "-tag-error"); | ||||
|         // noinspection JSValidateTypes
 | ||||
| @@ -459,7 +459,7 @@ class TagTabPlane extends TabPlane { | ||||
|                 if (tagButton.dataset.value === tabPlane.tag.value) { | ||||
|                     tagButton.classList.remove("btn-outline-primary"); | ||||
|                     tagButton.classList.add("btn-primary"); | ||||
|                     tabPlane.helper.filterSuggestedAccounts(tagButton); | ||||
|                     tabPlane.editor.filterSuggestedAccounts(tagButton); | ||||
|                     isMatched = true; | ||||
|                 } else { | ||||
|                     tagButton.classList.remove("btn-primary"); | ||||
| @@ -467,7 +467,7 @@ class TagTabPlane extends TabPlane { | ||||
|                 } | ||||
|             } | ||||
|             if (!isMatched) { | ||||
|                 tabPlane.helper.filterSuggestedAccounts(null); | ||||
|                 tabPlane.editor.filterSuggestedAccounts(null); | ||||
|             } | ||||
|             tabPlane.updateSummary(); | ||||
|             tabPlane.validateTag(); | ||||
| @@ -494,7 +494,7 @@ class TagTabPlane extends TabPlane { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         this.helper.filterSuggestedAccounts(selectedTagButton); | ||||
|         this.editor.filterSuggestedAccounts(selectedTagButton); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -512,7 +512,7 @@ class TagTabPlane extends TabPlane { | ||||
|                 tagButton.classList.remove("btn-outline-primary"); | ||||
|                 tagButton.classList.add("btn-primary"); | ||||
|                 tabPlane.tag.value = tagButton.dataset.value; | ||||
|                 tabPlane.helper.filterSuggestedAccounts(tagButton); | ||||
|                 tabPlane.editor.filterSuggestedAccounts(tagButton); | ||||
|                 tabPlane.updateSummary(); | ||||
|             }; | ||||
|         } | ||||
| @@ -589,12 +589,12 @@ class GeneralTagTab extends TagTabPlane { | ||||
|      * @override | ||||
|      */ | ||||
|     updateSummary() { | ||||
|         const pos = this.helper.summary.value.indexOf("—"); | ||||
|         const pos = this.editor.summary.value.indexOf("—"); | ||||
|         const prefix = this.tag.value === ""? "": this.tag.value + "—"; | ||||
|         if (pos === -1) { | ||||
|             this.helper.summary.value = prefix + this.helper.summary.value; | ||||
|             this.editor.summary.value = prefix + this.editor.summary.value; | ||||
|         } else { | ||||
|             this.helper.summary.value = prefix + this.helper.summary.value.substring(pos + 1); | ||||
|             this.editor.summary.value = prefix + this.editor.summary.value.substring(pos + 1); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @@ -605,7 +605,7 @@ class GeneralTagTab extends TagTabPlane { | ||||
|      * @override | ||||
|      */ | ||||
|     populate() { | ||||
|         const found = this.helper.summary.value.match(/^([^—]+)—.+?(?:×\d+)?$/); | ||||
|         const found = this.editor.summary.value.match(/^([^—]+)—.+?(?:×\d+)?$/); | ||||
|         if (found === null) { | ||||
|             return false; | ||||
|         } | ||||
| @@ -614,7 +614,7 @@ class GeneralTagTab extends TagTabPlane { | ||||
|             if (tagButton.dataset.value === this.tag.value) { | ||||
|                 tagButton.classList.remove("btn-outline-primary"); | ||||
|                 tagButton.classList.add("btn-primary"); | ||||
|                 this.helper.filterSuggestedAccounts(tagButton); | ||||
|                 this.editor.filterSuggestedAccounts(tagButton); | ||||
|             } | ||||
|         } | ||||
|         this.switchToMe(); | ||||
| @@ -671,11 +671,11 @@ class GeneralTripTab extends TagTabPlane { | ||||
|     /** | ||||
|      * Constructs a tab plane. | ||||
|      * | ||||
|      * @param helper {SummaryHelper} the parent summary helper | ||||
|      * @param editor {SummaryEditor} the parent summary editor | ||||
|      * @override | ||||
|      */ | ||||
|     constructor(helper) { | ||||
|         super(helper); | ||||
|     constructor(editor) { | ||||
|         super(editor); | ||||
|         this.#from = document.getElementById(this.prefix + "-from"); | ||||
|         this.#fromError = document.getElementById(this.prefix + "-from-error"); | ||||
|         this.#to = document.getElementById(this.prefix + "-to"); | ||||
| @@ -727,7 +727,7 @@ class GeneralTripTab extends TagTabPlane { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         this.helper.summary.value = this.tag.value + "—" + this.#from.value + direction + this.#to.value; | ||||
|         this.editor.summary.value = this.tag.value + "—" + this.#from.value + direction + this.#to.value; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -761,7 +761,7 @@ class GeneralTripTab extends TagTabPlane { | ||||
|      * @override | ||||
|      */ | ||||
|     populate() { | ||||
|         const found = this.helper.summary.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:×\d+)?$/); | ||||
|         const found = this.editor.summary.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:×\d+)?$/); | ||||
|         if (found === null) { | ||||
|             return false; | ||||
|         } | ||||
| @@ -781,7 +781,7 @@ class GeneralTripTab extends TagTabPlane { | ||||
|             if (tagButton.dataset.value === this.tag.value) { | ||||
|                 tagButton.classList.remove("btn-outline-primary"); | ||||
|                 tagButton.classList.add("btn-primary"); | ||||
|                 this.helper.filterSuggestedAccounts(tagButton); | ||||
|                 this.editor.filterSuggestedAccounts(tagButton); | ||||
|             } | ||||
|         } | ||||
|         this.switchToMe(); | ||||
| @@ -879,11 +879,11 @@ class BusTripTab extends TagTabPlane { | ||||
|     /** | ||||
|      * Constructs a tab plane. | ||||
|      * | ||||
|      * @param helper {SummaryHelper} the parent summary helper | ||||
|      * @param editor {SummaryEditor} the parent summary editor | ||||
|      * @override | ||||
|      */ | ||||
|     constructor(helper) { | ||||
|         super(helper); | ||||
|     constructor(editor) { | ||||
|         super(editor); | ||||
|         this.#route = document.getElementById(this.prefix + "-route"); | ||||
|         this.#routeError = document.getElementById(this.prefix + "-route-error"); | ||||
|         this.#from = document.getElementById(this.prefix + "-from"); | ||||
| @@ -921,7 +921,7 @@ class BusTripTab extends TagTabPlane { | ||||
|      * @override | ||||
|      */ | ||||
|     updateSummary() { | ||||
|         this.helper.summary.value = this.tag.value + "—" + this.#route.value + "—" + this.#from.value + "→" + this.#to.value; | ||||
|         this.editor.summary.value = this.tag.value + "—" + this.#route.value + "—" + this.#from.value + "→" + this.#to.value; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -949,7 +949,7 @@ class BusTripTab extends TagTabPlane { | ||||
|      * @override | ||||
|      */ | ||||
|     populate() { | ||||
|         const found = this.helper.summary.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:×\d+)?$/); | ||||
|         const found = this.editor.summary.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:×\d+)?$/); | ||||
|         if (found === null) { | ||||
|             return false; | ||||
|         } | ||||
| @@ -961,7 +961,7 @@ class BusTripTab extends TagTabPlane { | ||||
|             if (tagButton.dataset.value === this.tag.value) { | ||||
|                 tagButton.classList.remove("btn-outline-primary"); | ||||
|                 tagButton.classList.add("btn-primary"); | ||||
|                 this.helper.filterSuggestedAccounts(tagButton); | ||||
|                 this.editor.filterSuggestedAccounts(tagButton); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| @@ -1041,11 +1041,11 @@ class RegularPaymentTab extends TabPlane { | ||||
|     /** | ||||
|      * Constructs a tab plane. | ||||
|      * | ||||
|      * @param helper {SummaryHelper} the parent summary helper | ||||
|      * @param editor {SummaryEditor} the parent summary editor | ||||
|      * @override | ||||
|      */ | ||||
|     constructor(helper) { | ||||
|         super(helper); | ||||
|     constructor(editor) { | ||||
|         super(editor); | ||||
|         // noinspection JSValidateTypes
 | ||||
|         this.#payments = Array.from(document.getElementsByClassName(this.prefix + "-payment")); | ||||
|     } | ||||
| @@ -1103,19 +1103,19 @@ class NumberTab extends TabPlane { | ||||
|     /** | ||||
|      * Constructs a tab plane. | ||||
|      * | ||||
|      * @param helper {SummaryHelper} the parent summary helper | ||||
|      * @param editor {SummaryEditor} the parent summary editor | ||||
|      * @override | ||||
|      */ | ||||
|     constructor(helper) { | ||||
|         super(helper); | ||||
|     constructor(editor) { | ||||
|         super(editor); | ||||
|         const tabPlane = this; | ||||
|         this.helper.number.onchange = function () { | ||||
|             const found = tabPlane.helper.summary.value.match(/^(.+)×(\d+)$/); | ||||
|         this.editor.number.onchange = function () { | ||||
|             const found = tabPlane.editor.summary.value.match(/^(.+)×(\d+)$/); | ||||
|             if (found !== null) { | ||||
|                 tabPlane.helper.summary.value = found[1]; | ||||
|                 tabPlane.editor.summary.value = found[1]; | ||||
|             } | ||||
|             if (parseInt(tabPlane.helper.number.value) > 1) { | ||||
|                 tabPlane.helper.summary.value = tabPlane.helper.summary.value + "×" + tabPlane.helper.number.value; | ||||
|             if (parseInt(tabPlane.editor.number.value) > 1) { | ||||
|                 tabPlane.editor.summary.value = tabPlane.editor.summary.value + "×" + tabPlane.editor.number.value; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| @@ -1136,7 +1136,7 @@ class NumberTab extends TabPlane { | ||||
|      * @override | ||||
|      */ | ||||
|     reset() { | ||||
|         this.helper.number.value = ""; | ||||
|         this.editor.number.value = ""; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -1146,11 +1146,11 @@ class NumberTab extends TabPlane { | ||||
|      * @override | ||||
|      */ | ||||
|     populate() { | ||||
|         const found = this.helper.summary.value.match(/^.+×(\d+)$/); | ||||
|         const found = this.editor.summary.value.match(/^.+×(\d+)$/); | ||||
|         if (found === null) { | ||||
|             this.helper.number.value = ""; | ||||
|             this.editor.number.value = ""; | ||||
|         } else { | ||||
|             this.helper.number.value = found[1]; | ||||
|             this.editor.number.value = found[1]; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| @@ -171,7 +171,7 @@ function initializeNewEntryButton(button) { | ||||
|         formAccount.dataset.code = ""; | ||||
|         formAccount.dataset.text = ""; | ||||
|         formAccountError.innerText = ""; | ||||
|         formSummaryControl.dataset.bsTarget = "#accounting-summary-helper-" + button.dataset.entryType + "-modal"; | ||||
|         formSummaryControl.dataset.bsTarget = "#accounting-summary-editor-" + button.dataset.entryType + "-modal"; | ||||
|         formSummaryControl.classList.remove("accounting-not-empty"); | ||||
|         formSummaryControl.classList.remove("is-invalid"); | ||||
|         formSummary.dataset.value = ""; | ||||
| @@ -181,7 +181,7 @@ function initializeNewEntryButton(button) { | ||||
|         formAmount.classList.remove("is-invalid"); | ||||
|         formAmountError.innerText = ""; | ||||
|         AccountSelector.initializeJournalEntryForm(); | ||||
|         SummaryHelper.initializeNewJournalEntry(button.dataset.entryType); | ||||
|         SummaryEditor.initializeNewJournalEntry(button.dataset.entryType); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| @@ -228,7 +228,7 @@ function initializeJournalEntry(entry) { | ||||
|         formAccount.innerText = accountCode.dataset.text; | ||||
|         formAccount.dataset.code = accountCode.value; | ||||
|         formAccount.dataset.text = accountCode.dataset.text; | ||||
|         formSummaryControl.dataset.bsTarget = "#accounting-summary-helper-" + entry.dataset.entryType + "-modal"; | ||||
|         formSummaryControl.dataset.bsTarget = "#accounting-summary-editor-" + entry.dataset.entryType + "-modal"; | ||||
|         if (summary.value === "") { | ||||
|             formSummaryControl.classList.remove("accounting-not-empty"); | ||||
|         } else { | ||||
|   | ||||
| @@ -46,8 +46,8 @@ First written: 2023/2/25 | ||||
| {% endblock %} | ||||
|  | ||||
| {% block form_modals %} | ||||
|   {% with summary_helper = form.summary_helper.debit %} | ||||
|     {% include "accounting/transaction/include/summary-helper-modal.html" %} | ||||
|   {% with summary_editor = form.summary_editor.debit %} | ||||
|     {% include "accounting/transaction/include/summary-editor-modal.html" %} | ||||
|   {% endwith %} | ||||
|   {% with entry_type = "debit", | ||||
|           account_options = form.debit_account_options %} | ||||
|   | ||||
| @@ -25,7 +25,7 @@ First written: 2023/2/26 | ||||
|   <script src="{{ url_for("accounting.static", filename="js/drag-and-drop-reorder.js") }}"></script> | ||||
|   <script src="{{ url_for("accounting.static", filename="js/transaction-form.js") }}"></script> | ||||
|   <script src="{{ url_for("accounting.static", filename="js/account-selector.js") }}"></script> | ||||
|   <script src="{{ url_for("accounting.static", filename="js/summary-helper.js") }}"></script> | ||||
|   <script src="{{ url_for("accounting.static", filename="js/summary-editor.js") }}"></script> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|   | ||||
| @@ -0,0 +1,181 @@ | ||||
| {# | ||||
| The Mia! Accounting Flask Project | ||||
| summary-editor-modal.html: The modal of the summary editor | ||||
|  | ||||
|  Copyright (c) 2023 imacat. | ||||
|  | ||||
|  Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  you may not use this file except in compliance with the License. | ||||
|  You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|  Unless required by applicable law or agreed to in writing, software | ||||
|  distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  See the License for the specific language governing permissions and | ||||
|  limitations under the License. | ||||
|  | ||||
| Author: imacat@mail.imacat.idv.tw (imacat) | ||||
| First written: 2023/2/28 | ||||
| #} | ||||
| <form id="accounting-summary-editor-{{ summary_editor.type }}" class="accounting-summary-editor" data-entry-type="{{ summary_editor.type }}"> | ||||
|   <div id="accounting-summary-editor-{{ summary_editor.type }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-modal-label" aria-hidden="true"> | ||||
|     <div class="modal-dialog"> | ||||
|       <div class="modal-content"> | ||||
|         <div class="modal-header"> | ||||
|           <h1 class="modal-title fs-5" id="accounting-summary-editor-{{ summary_editor.type }}-modal-label"> | ||||
|             <label for="accounting-summary-editor-{{ summary_editor.type }}-summary">{{ A_("Summary") }}</label> | ||||
|           </h1> | ||||
|           <button class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal" aria-label="{{ A_("Close") }}"></button> | ||||
|         </div> | ||||
|         <div class="modal-body"> | ||||
|           <div class="mb-3"> | ||||
|             <input id="accounting-summary-editor-{{ summary_editor.type }}-summary" class="form-control" type="text" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-modal-label"> | ||||
|           </div> | ||||
|           <ul class="nav nav-tabs mb-2"> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-editor-{{ summary_editor.type }}-general-tab" class="nav-link active accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="page" data-tab-id="general"> | ||||
|                 {{ A_("General") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-editor-{{ summary_editor.type }}-travel-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="travel"> | ||||
|                 {{ A_("Travel") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-editor-{{ summary_editor.type }}-bus-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="bus"> | ||||
|                 {{ A_("Bus") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-editor-{{ summary_editor.type }}-regular-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="regular"> | ||||
|                 {{ A_("Regular") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-editor-{{ summary_editor.type }}-number-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="number"> | ||||
|                 {{ A_("Number") }} | ||||
|               </span> | ||||
|             </li> | ||||
|           </ul> | ||||
|           {# A general summary with a tag #} | ||||
|           <div id="accounting-summary-editor-{{ summary_editor.type }}-general-page" class="accounting-summary-editor-{{ summary_editor.type }}-page" aria-current="page" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-general" data-tab-id="general"> | ||||
|             <div class="form-floating mb-2"> | ||||
|               <input id="accounting-summary-editor-{{ summary_editor.type }}-general-tag" class="form-control" type="text" value="" placeholder=" "> | ||||
|               <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-general-tag">{{ A_("Tag") }}</label> | ||||
|               <div id="accounting-summary-editor-{{ summary_editor.type }}-general-tag-error" class="invalid-feedback"></div> | ||||
|             </div> | ||||
|  | ||||
|             <div> | ||||
|               {% for tag in summary_editor.general.tags %} | ||||
|                 <button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-general-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}"> | ||||
|                   {{ tag }} | ||||
|                 </button> | ||||
|               {% endfor %} | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# A general trip with the origin and distination #} | ||||
|           <div id="accounting-summary-editor-{{ summary_editor.type }}-travel-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-travel" data-tab-id="travel"> | ||||
|             <div class="form-floating mb-2"> | ||||
|               <input id="accounting-summary-editor-{{ summary_editor.type }}-travel-tag" class="form-control" type="text" value="" placeholder=" "> | ||||
|               <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-travel-tag">{{ A_("Tag") }}</label> | ||||
|               <div id="accounting-summary-editor-{{ summary_editor.type }}-travel-tag-error" class="invalid-feedback"></div> | ||||
|             </div> | ||||
|  | ||||
|             <div> | ||||
|               {% for tag in summary_editor.travel.tags %} | ||||
|                 <button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-travel-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}"> | ||||
|                   {{ tag }} | ||||
|                 </button> | ||||
|               {% endfor %} | ||||
|             </div> | ||||
|  | ||||
|             <div class="d-flex justify-content-between mt-2"> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-editor-{{ summary_editor.type }}-travel-from" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-travel-from">{{ A_("From") }}</label> | ||||
|                 <div id="accounting-summary-editor-{{ summary_editor.type }}-travel-from-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|               <div class="btn-group-vertical ms-1 me-1"> | ||||
|                 <button class="btn btn-primary accounting-summary-editor-{{ summary_editor.type }}-travel-direction accounting-default" type="button" tabindex="-1" data-arrow="→">→</button> | ||||
|                 <button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-travel-direction" type="button" tabindex="-1" data-arrow="↔">↔</button> | ||||
|               </div> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-editor-{{ summary_editor.type }}-travel-to" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-travel-to">{{ A_("To") }}</label> | ||||
|                 <div id="accounting-summary-editor-{{ summary_editor.type }}-travel-to-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# A bus trip with the route name or route number, the origin and distination #} | ||||
|           <div id="accounting-summary-editor-{{ summary_editor.type }}-bus-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-bus" data-tab-id="bus"> | ||||
|             <div class="d-flex justify-content-between mb-2"> | ||||
|               <div class="form-floating me-2"> | ||||
|                 <input id="accounting-summary-editor-{{ summary_editor.type }}-bus-tag" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-tag">{{ A_("Tag") }}</label> | ||||
|                 <div id="accounting-summary-editor-{{ summary_editor.type }}-bus-tag-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-editor-{{ summary_editor.type }}-bus-route" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-route">{{ A_("Route") }}</label> | ||||
|                 <div id="accounting-summary-editor-{{ summary_editor.type }}-bus-route-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|             </div> | ||||
|  | ||||
|             <div> | ||||
|               {% for tag in summary_editor.bus.tags %} | ||||
|                 <button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-bus-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}"> | ||||
|                   {{ tag }} | ||||
|                 </button> | ||||
|               {% endfor %} | ||||
|             </div> | ||||
|  | ||||
|             <div class="d-flex justify-content-between mt-2"> | ||||
|               <div class="form-floating me-2"> | ||||
|                 <input id="accounting-summary-editor-{{ summary_editor.type }}-bus-from" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-from">{{ A_("From") }}</label> | ||||
|                 <div id="accounting-summary-editor-{{ summary_editor.type }}-bus-from-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-editor-{{ summary_editor.type }}-bus-to" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-to">{{ A_("To") }}</label> | ||||
|                 <div id="accounting-summary-editor-{{ summary_editor.type }}-bus-to-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# A regular income or payment #} | ||||
|           <div id="accounting-summary-editor-{{ summary_editor.type }}-regular-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-regular" data-tab-id="regular"> | ||||
|             {# TODO: To be done #} | ||||
|           </div> | ||||
|  | ||||
|           {# The number of items #} | ||||
|           <div id="accounting-summary-editor-{{ summary_editor.type }}-number-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-number" data-tab-id="number"> | ||||
|             <div class="form-floating"> | ||||
|               <input id="accounting-summary-editor-{{ summary_editor.type }}-number-number" class="form-control" type="number" min="1" value="" placeholder=" "> | ||||
|               <label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-number">{{ A_("The number of items") }}</label> | ||||
|               <div id="accounting-summary-editor-{{ summary_editor.type }}-number-error" class="invalid-feedback"></div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# The suggested accounts #} | ||||
|           <div class="mt-3"> | ||||
|             {% for account in summary_editor.accounts %} | ||||
|               <button class="btn btn-outline-primary d-none accounting-summary-editor-{{ summary_editor.type }}-account" type="button" data-code="{{ account.code }}" data-text="{{ account }}"> | ||||
|                 {{ account }} | ||||
|               </button> | ||||
|             {% endfor %} | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="modal-footer"> | ||||
|           <button class="btn btn-secondary" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal">{{ A_("Cancel") }}</button> | ||||
|           <button id="accounting-summary-editor-{{ summary_editor.type }}-btn-save" type="submit" class="btn btn-primary">{{ A_("Save") }}</button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </form> | ||||
| @@ -1,181 +0,0 @@ | ||||
| {# | ||||
| The Mia! Accounting Flask Project | ||||
| entry-form-modal.html: The modal of the summary helper | ||||
|  | ||||
|  Copyright (c) 2023 imacat. | ||||
|  | ||||
|  Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  you may not use this file except in compliance with the License. | ||||
|  You may obtain a copy of the License at | ||||
|  | ||||
|      http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|  Unless required by applicable law or agreed to in writing, software | ||||
|  distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  See the License for the specific language governing permissions and | ||||
|  limitations under the License. | ||||
|  | ||||
| Author: imacat@mail.imacat.idv.tw (imacat) | ||||
| First written: 2023/2/28 | ||||
| #} | ||||
| <form id="accounting-summary-helper-{{ summary_helper.type }}" class="accounting-summary-helper" data-entry-type="{{ summary_helper.type }}"> | ||||
|   <div id="accounting-summary-helper-{{ summary_helper.type }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-modal-label" aria-hidden="true"> | ||||
|     <div class="modal-dialog"> | ||||
|       <div class="modal-content"> | ||||
|         <div class="modal-header"> | ||||
|           <h1 class="modal-title fs-5" id="accounting-summary-helper-{{ summary_helper.type }}-modal-label"> | ||||
|             <label for="accounting-summary-helper-{{ summary_helper.type }}-summary">{{ A_("Summary") }}</label> | ||||
|           </h1> | ||||
|           <button class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal" aria-label="{{ A_("Close") }}"></button> | ||||
|         </div> | ||||
|         <div class="modal-body"> | ||||
|           <div class="mb-3"> | ||||
|             <input id="accounting-summary-helper-{{ summary_helper.type }}-summary" class="form-control" type="text" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-modal-label"> | ||||
|           </div> | ||||
|           <ul class="nav nav-tabs mb-2"> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-helper-{{ summary_helper.type }}-general-tab" class="nav-link active accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="page" data-tab-id="general"> | ||||
|                 {{ A_("General") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-helper-{{ summary_helper.type }}-travel-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="travel"> | ||||
|                 {{ A_("Travel") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-helper-{{ summary_helper.type }}-bus-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="bus"> | ||||
|                 {{ A_("Bus") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-helper-{{ summary_helper.type }}-regular-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="regular"> | ||||
|                 {{ A_("Regular") }} | ||||
|               </span> | ||||
|             </li> | ||||
|             <li class="nav-item"> | ||||
|               <span id="accounting-summary-helper-{{ summary_helper.type }}-number-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="number"> | ||||
|                 {{ A_("Number") }} | ||||
|               </span> | ||||
|             </li> | ||||
|           </ul> | ||||
|           {# A general summary with a tag #} | ||||
|           <div id="accounting-summary-helper-{{ summary_helper.type }}-general-page" class="accounting-summary-helper-{{ summary_helper.type }}-page" aria-current="page" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-general" data-tab-id="general"> | ||||
|             <div class="form-floating mb-2"> | ||||
|               <input id="accounting-summary-helper-{{ summary_helper.type }}-general-tag" class="form-control" type="text" value="" placeholder=" "> | ||||
|               <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-general-tag">{{ A_("Tag") }}</label> | ||||
|               <div id="accounting-summary-helper-{{ summary_helper.type }}-general-tag-error" class="invalid-feedback"></div> | ||||
|             </div> | ||||
|  | ||||
|             <div> | ||||
|               {% for tag in summary_helper.general.tags %} | ||||
|                 <button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-general-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}"> | ||||
|                   {{ tag }} | ||||
|                 </button> | ||||
|               {% endfor %} | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# A general trip with the origin and distination #} | ||||
|           <div id="accounting-summary-helper-{{ summary_helper.type }}-travel-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-travel" data-tab-id="travel"> | ||||
|             <div class="form-floating mb-2"> | ||||
|               <input id="accounting-summary-helper-{{ summary_helper.type }}-travel-tag" class="form-control" type="text" value="" placeholder=" "> | ||||
|               <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-travel-tag">{{ A_("Tag") }}</label> | ||||
|               <div id="accounting-summary-helper-{{ summary_helper.type }}-travel-tag-error" class="invalid-feedback"></div> | ||||
|             </div> | ||||
|  | ||||
|             <div> | ||||
|               {% for tag in summary_helper.travel.tags %} | ||||
|                 <button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-travel-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}"> | ||||
|                   {{ tag }} | ||||
|                 </button> | ||||
|               {% endfor %} | ||||
|             </div> | ||||
|  | ||||
|             <div class="d-flex justify-content-between mt-2"> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-helper-{{ summary_helper.type }}-travel-from" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-travel-from">{{ A_("From") }}</label> | ||||
|                 <div id="accounting-summary-helper-{{ summary_helper.type }}-travel-from-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|               <div class="btn-group-vertical ms-1 me-1"> | ||||
|                 <button class="btn btn-primary accounting-summary-helper-{{ summary_helper.type }}-travel-direction accounting-default" type="button" tabindex="-1" data-arrow="→">→</button> | ||||
|                 <button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-travel-direction" type="button" tabindex="-1" data-arrow="↔">↔</button> | ||||
|               </div> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-helper-{{ summary_helper.type }}-travel-to" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-travel-to">{{ A_("To") }}</label> | ||||
|                 <div id="accounting-summary-helper-{{ summary_helper.type }}-travel-to-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# A bus trip with the route name or route number, the origin and distination #} | ||||
|           <div id="accounting-summary-helper-{{ summary_helper.type }}-bus-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-bus" data-tab-id="bus"> | ||||
|             <div class="d-flex justify-content-between mb-2"> | ||||
|               <div class="form-floating me-2"> | ||||
|                 <input id="accounting-summary-helper-{{ summary_helper.type }}-bus-tag" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-tag">{{ A_("Tag") }}</label> | ||||
|                 <div id="accounting-summary-helper-{{ summary_helper.type }}-bus-tag-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-helper-{{ summary_helper.type }}-bus-route" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-route">{{ A_("Route") }}</label> | ||||
|                 <div id="accounting-summary-helper-{{ summary_helper.type }}-bus-route-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|             </div> | ||||
|  | ||||
|             <div> | ||||
|               {% for tag in summary_helper.bus.tags %} | ||||
|                 <button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-bus-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}"> | ||||
|                   {{ tag }} | ||||
|                 </button> | ||||
|               {% endfor %} | ||||
|             </div> | ||||
|  | ||||
|             <div class="d-flex justify-content-between mt-2"> | ||||
|               <div class="form-floating me-2"> | ||||
|                 <input id="accounting-summary-helper-{{ summary_helper.type }}-bus-from" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-from">{{ A_("From") }}</label> | ||||
|                 <div id="accounting-summary-helper-{{ summary_helper.type }}-bus-from-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|               <div class="form-floating"> | ||||
|                 <input id="accounting-summary-helper-{{ summary_helper.type }}-bus-to" class="form-control" type="text" value="" placeholder=" "> | ||||
|                 <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-to">{{ A_("To") }}</label> | ||||
|                 <div id="accounting-summary-helper-{{ summary_helper.type }}-bus-to-error" class="invalid-feedback"></div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# A regular income or payment #} | ||||
|           <div id="accounting-summary-helper-{{ summary_helper.type }}-regular-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-regular" data-tab-id="regular"> | ||||
|             {# TODO: To be done #} | ||||
|           </div> | ||||
|  | ||||
|           {# The number of items #} | ||||
|           <div id="accounting-summary-helper-{{ summary_helper.type }}-number-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-number" data-tab-id="number"> | ||||
|             <div class="form-floating"> | ||||
|               <input id="accounting-summary-helper-{{ summary_helper.type }}-number-number" class="form-control" type="number" min="1" value="" placeholder=" "> | ||||
|               <label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-number">{{ A_("The number of items") }}</label> | ||||
|               <div id="accounting-summary-helper-{{ summary_helper.type }}-number-error" class="invalid-feedback"></div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           {# The suggested accounts #} | ||||
|           <div class="mt-3"> | ||||
|             {% for account in summary_helper.accounts %} | ||||
|               <button class="btn btn-outline-primary d-none accounting-summary-helper-{{ summary_helper.type }}-account" type="button" data-code="{{ account.code }}" data-text="{{ account }}"> | ||||
|                 {{ account }} | ||||
|               </button> | ||||
|             {% endfor %} | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="modal-footer"> | ||||
|           <button class="btn btn-secondary" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal">{{ A_("Cancel") }}</button> | ||||
|           <button id="accounting-summary-helper-{{ summary_helper.type }}-btn-save" type="submit" class="btn btn-primary">{{ A_("Save") }}</button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </form> | ||||
| @@ -46,8 +46,8 @@ First written: 2023/2/25 | ||||
| {% endblock %} | ||||
|  | ||||
| {% block form_modals %} | ||||
|   {% with summary_helper = form.summary_helper.credit %} | ||||
|     {% include "accounting/transaction/include/summary-helper-modal.html" %} | ||||
|   {% with summary_editor = form.summary_editor.credit %} | ||||
|     {% include "accounting/transaction/include/summary-editor-modal.html" %} | ||||
|   {% endwith %} | ||||
|   {% with entry_type = "credit", | ||||
|           account_options = form.credit_account_options %} | ||||
|   | ||||
| @@ -50,11 +50,11 @@ First written: 2023/2/25 | ||||
| {% endblock %} | ||||
|  | ||||
| {% block form_modals %} | ||||
|   {% with summary_helper = form.summary_helper.debit %} | ||||
|     {% include "accounting/transaction/include/summary-helper-modal.html" %} | ||||
|   {% with summary_editor = form.summary_editor.debit %} | ||||
|     {% include "accounting/transaction/include/summary-editor-modal.html" %} | ||||
|   {% endwith %} | ||||
|   {% with summary_helper = form.summary_helper.credit %} | ||||
|     {% include "accounting/transaction/include/summary-helper-modal.html" %} | ||||
|   {% with summary_editor = form.summary_editor.credit %} | ||||
|     {% include "accounting/transaction/include/summary-editor-modal.html" %} | ||||
|   {% endwith %} | ||||
|   {% with entry_type = "debit", | ||||
|           account_options = form.debit_account_options %} | ||||
|   | ||||
| @@ -37,7 +37,7 @@ from accounting import db | ||||
| from accounting.locale import lazy_gettext | ||||
| from accounting.models import Transaction, Account, JournalEntry, \ | ||||
|     TransactionCurrency, Currency | ||||
| from accounting.transaction.summary_helper import SummaryHelper | ||||
| from accounting.transaction.summary_editor import SummaryEditor | ||||
| from accounting.utils.random_id import new_id | ||||
| from accounting.utils.strip_text import strip_text, strip_multiline_text | ||||
| from accounting.utils.user import get_current_user_pk | ||||
| @@ -391,12 +391,12 @@ class TransactionForm(FlaskForm): | ||||
|                 if isinstance(x, str) or isinstance(x, LazyString)] | ||||
|  | ||||
|     @property | ||||
|     def summary_helper(self) -> SummaryHelper: | ||||
|         """Returns the summary helper. | ||||
|     def summary_editor(self) -> SummaryEditor: | ||||
|         """Returns the summary editor. | ||||
|  | ||||
|         :return: The summary helper. | ||||
|         :return: The summary editor. | ||||
|         """ | ||||
|         return SummaryHelper() | ||||
|         return SummaryEditor() | ||||
|  | ||||
|  | ||||
| T = t.TypeVar("T", bound=TransactionForm) | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
| #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| #  See the License for the specific language governing permissions and | ||||
| #  limitations under the License. | ||||
| """The summary helper. | ||||
| """The summary editor. | ||||
| 
 | ||||
| """ | ||||
| import typing as t | ||||
| @@ -178,7 +178,7 @@ class SummaryEntryType: | ||||
| 
 | ||||
|     @property | ||||
|     def accounts(self) -> list[SummaryAccount]: | ||||
|         """Returns the suggested accounts of all tags in the summary helper in | ||||
|         """Returns the suggested accounts of all tags in the summary editor in | ||||
|         the entry type, in their frequency order. | ||||
| 
 | ||||
|         :return: The suggested accounts of all tags, in their frequency order. | ||||
| @@ -197,11 +197,11 @@ class SummaryEntryType: | ||||
|                                             key=lambda x: -freq[x])] | ||||
| 
 | ||||
| 
 | ||||
| class SummaryHelper: | ||||
|     """The summary helper.""" | ||||
| class SummaryEditor: | ||||
|     """The summary editor.""" | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         """Constructs the summary helper.""" | ||||
|         """Constructs the summary editor.""" | ||||
|         self.debit: SummaryEntryType = SummaryEntryType("debit") | ||||
|         """The debit tags.""" | ||||
|         self.credit: SummaryEntryType = SummaryEntryType("credit") | ||||
| @@ -14,7 +14,7 @@ | ||||
| #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| #  See the License for the specific language governing permissions and | ||||
| #  limitations under the License. | ||||
| """The test for the summary helper. | ||||
| """The test for the summary editor. | ||||
| 
 | ||||
| """ | ||||
| import unittest | ||||
| @@ -29,8 +29,8 @@ from testlib import get_client | ||||
| from testlib_txn import Accounts, NEXT_URI, add_txn | ||||
| 
 | ||||
| 
 | ||||
| class SummeryHelperTestCase(unittest.TestCase): | ||||
|     """The summary helper test case.""" | ||||
| class SummeryEditorTestCase(unittest.TestCase): | ||||
|     """The summary editor test case.""" | ||||
| 
 | ||||
|     def setUp(self) -> None: | ||||
|         """Sets up the test. | ||||
| @@ -61,101 +61,101 @@ class SummeryHelperTestCase(unittest.TestCase): | ||||
| 
 | ||||
|         self.client, self.csrf_token = get_client(self.app, "editor") | ||||
| 
 | ||||
|     def test_summary_helper(self) -> None: | ||||
|         """Test the summary helper. | ||||
|     def test_summary_editor(self) -> None: | ||||
|         """Test the summary editor. | ||||
| 
 | ||||
|         :return: None. | ||||
|         """ | ||||
|         from accounting.transaction.summary_helper import SummaryHelper | ||||
|         from accounting.transaction.summary_editor import SummaryEditor | ||||
|         for form in get_form_data(self.csrf_token): | ||||
|             add_txn(self.client, form) | ||||
|         with self.app.app_context(): | ||||
|             helper: SummaryHelper = SummaryHelper() | ||||
|             editor: SummaryEditor = SummaryEditor() | ||||
| 
 | ||||
|         # Debit-General | ||||
|         self.assertEqual(len(helper.debit.general.tags), 2) | ||||
|         self.assertEqual(helper.debit.general.tags[0].name, "Lunch") | ||||
|         self.assertEqual(len(helper.debit.general.tags[0].accounts), 2) | ||||
|         self.assertEqual(helper.debit.general.tags[0].accounts[0].code, | ||||
|         self.assertEqual(len(editor.debit.general.tags), 2) | ||||
|         self.assertEqual(editor.debit.general.tags[0].name, "Lunch") | ||||
|         self.assertEqual(len(editor.debit.general.tags[0].accounts), 2) | ||||
|         self.assertEqual(editor.debit.general.tags[0].accounts[0].code, | ||||
|                          Accounts.MEAL) | ||||
|         self.assertEqual(helper.debit.general.tags[0].accounts[1].code, | ||||
|         self.assertEqual(editor.debit.general.tags[0].accounts[1].code, | ||||
|                          Accounts.PAYABLE) | ||||
|         self.assertEqual(helper.debit.general.tags[1].name, "Dinner") | ||||
|         self.assertEqual(len(helper.debit.general.tags[1].accounts), 2) | ||||
|         self.assertEqual(helper.debit.general.tags[1].accounts[0].code, | ||||
|         self.assertEqual(editor.debit.general.tags[1].name, "Dinner") | ||||
|         self.assertEqual(len(editor.debit.general.tags[1].accounts), 2) | ||||
|         self.assertEqual(editor.debit.general.tags[1].accounts[0].code, | ||||
|                          Accounts.MEAL) | ||||
|         self.assertEqual(helper.debit.general.tags[1].accounts[1].code, | ||||
|         self.assertEqual(editor.debit.general.tags[1].accounts[1].code, | ||||
|                          Accounts.PAYABLE) | ||||
| 
 | ||||
|         # Debit-Travel | ||||
|         self.assertEqual(len(helper.debit.travel.tags), 3) | ||||
|         self.assertEqual(helper.debit.travel.tags[0].name, "Bike") | ||||
|         self.assertEqual(len(helper.debit.travel.tags[0].accounts), 1) | ||||
|         self.assertEqual(helper.debit.travel.tags[0].accounts[0].code, | ||||
|         self.assertEqual(len(editor.debit.travel.tags), 3) | ||||
|         self.assertEqual(editor.debit.travel.tags[0].name, "Bike") | ||||
|         self.assertEqual(len(editor.debit.travel.tags[0].accounts), 1) | ||||
|         self.assertEqual(editor.debit.travel.tags[0].accounts[0].code, | ||||
|                          Accounts.TRAVEL) | ||||
|         self.assertEqual(helper.debit.travel.tags[1].name, "Taxi") | ||||
|         self.assertEqual(len(helper.debit.travel.tags[1].accounts), 1) | ||||
|         self.assertEqual(helper.debit.travel.tags[1].accounts[0].code, | ||||
|         self.assertEqual(editor.debit.travel.tags[1].name, "Taxi") | ||||
|         self.assertEqual(len(editor.debit.travel.tags[1].accounts), 1) | ||||
|         self.assertEqual(editor.debit.travel.tags[1].accounts[0].code, | ||||
|                          Accounts.TRAVEL) | ||||
|         self.assertEqual(helper.debit.travel.tags[2].name, "Airplane") | ||||
|         self.assertEqual(len(helper.debit.travel.tags[2].accounts), 1) | ||||
|         self.assertEqual(helper.debit.travel.tags[2].accounts[0].code, | ||||
|         self.assertEqual(editor.debit.travel.tags[2].name, "Airplane") | ||||
|         self.assertEqual(len(editor.debit.travel.tags[2].accounts), 1) | ||||
|         self.assertEqual(editor.debit.travel.tags[2].accounts[0].code, | ||||
|                          Accounts.TRAVEL) | ||||
| 
 | ||||
|         # Debit-Bus | ||||
|         self.assertEqual(len(helper.debit.bus.tags), 2) | ||||
|         self.assertEqual(helper.debit.bus.tags[0].name, "Train") | ||||
|         self.assertEqual(len(helper.debit.bus.tags[0].accounts), 1) | ||||
|         self.assertEqual(helper.debit.bus.tags[0].accounts[0].code, | ||||
|         self.assertEqual(len(editor.debit.bus.tags), 2) | ||||
|         self.assertEqual(editor.debit.bus.tags[0].name, "Train") | ||||
|         self.assertEqual(len(editor.debit.bus.tags[0].accounts), 1) | ||||
|         self.assertEqual(editor.debit.bus.tags[0].accounts[0].code, | ||||
|                          Accounts.TRAVEL) | ||||
|         self.assertEqual(helper.debit.bus.tags[1].name, "Bus") | ||||
|         self.assertEqual(len(helper.debit.bus.tags[1].accounts), 1) | ||||
|         self.assertEqual(helper.debit.bus.tags[1].accounts[0].code, | ||||
|         self.assertEqual(editor.debit.bus.tags[1].name, "Bus") | ||||
|         self.assertEqual(len(editor.debit.bus.tags[1].accounts), 1) | ||||
|         self.assertEqual(editor.debit.bus.tags[1].accounts[0].code, | ||||
|                          Accounts.TRAVEL) | ||||
| 
 | ||||
|         # Credit-General | ||||
|         self.assertEqual(len(helper.credit.general.tags), 2) | ||||
|         self.assertEqual(helper.credit.general.tags[0].name, "Lunch") | ||||
|         self.assertEqual(len(helper.credit.general.tags[0].accounts), 3) | ||||
|         self.assertEqual(helper.credit.general.tags[0].accounts[0].code, | ||||
|         self.assertEqual(len(editor.credit.general.tags), 2) | ||||
|         self.assertEqual(editor.credit.general.tags[0].name, "Lunch") | ||||
|         self.assertEqual(len(editor.credit.general.tags[0].accounts), 3) | ||||
|         self.assertEqual(editor.credit.general.tags[0].accounts[0].code, | ||||
|                          Accounts.PAYABLE) | ||||
|         self.assertEqual(helper.credit.general.tags[0].accounts[1].code, | ||||
|         self.assertEqual(editor.credit.general.tags[0].accounts[1].code, | ||||
|                          Accounts.BANK) | ||||
|         self.assertEqual(helper.credit.general.tags[0].accounts[2].code, | ||||
|         self.assertEqual(editor.credit.general.tags[0].accounts[2].code, | ||||
|                          Accounts.CASH) | ||||
|         self.assertEqual(helper.credit.general.tags[1].name, "Dinner") | ||||
|         self.assertEqual(len(helper.credit.general.tags[1].accounts), 2) | ||||
|         self.assertEqual(helper.credit.general.tags[1].accounts[0].code, | ||||
|         self.assertEqual(editor.credit.general.tags[1].name, "Dinner") | ||||
|         self.assertEqual(len(editor.credit.general.tags[1].accounts), 2) | ||||
|         self.assertEqual(editor.credit.general.tags[1].accounts[0].code, | ||||
|                          Accounts.BANK) | ||||
|         self.assertEqual(helper.credit.general.tags[1].accounts[1].code, | ||||
|         self.assertEqual(editor.credit.general.tags[1].accounts[1].code, | ||||
|                          Accounts.PAYABLE) | ||||
| 
 | ||||
|         # Credit-Travel | ||||
|         self.assertEqual(len(helper.credit.travel.tags), 2) | ||||
|         self.assertEqual(helper.credit.travel.tags[0].name, "Bike") | ||||
|         self.assertEqual(len(helper.credit.travel.tags[0].accounts), 2) | ||||
|         self.assertEqual(helper.credit.travel.tags[0].accounts[0].code, | ||||
|         self.assertEqual(len(editor.credit.travel.tags), 2) | ||||
|         self.assertEqual(editor.credit.travel.tags[0].name, "Bike") | ||||
|         self.assertEqual(len(editor.credit.travel.tags[0].accounts), 2) | ||||
|         self.assertEqual(editor.credit.travel.tags[0].accounts[0].code, | ||||
|                          Accounts.PAYABLE) | ||||
|         self.assertEqual(helper.credit.travel.tags[0].accounts[1].code, | ||||
|         self.assertEqual(editor.credit.travel.tags[0].accounts[1].code, | ||||
|                          Accounts.PREPAID) | ||||
|         self.assertEqual(helper.credit.travel.tags[1].name, "Taxi") | ||||
|         self.assertEqual(len(helper.credit.travel.tags[1].accounts), 2) | ||||
|         self.assertEqual(helper.credit.travel.tags[1].accounts[0].code, | ||||
|         self.assertEqual(editor.credit.travel.tags[1].name, "Taxi") | ||||
|         self.assertEqual(len(editor.credit.travel.tags[1].accounts), 2) | ||||
|         self.assertEqual(editor.credit.travel.tags[1].accounts[0].code, | ||||
|                          Accounts.PAYABLE) | ||||
|         self.assertEqual(helper.credit.travel.tags[1].accounts[1].code, | ||||
|         self.assertEqual(editor.credit.travel.tags[1].accounts[1].code, | ||||
|                          Accounts.CASH) | ||||
| 
 | ||||
|         # Credit-Bus | ||||
|         self.assertEqual(len(helper.credit.bus.tags), 2) | ||||
|         self.assertEqual(helper.credit.bus.tags[0].name, "Train") | ||||
|         self.assertEqual(len(helper.credit.bus.tags[0].accounts), 2) | ||||
|         self.assertEqual(helper.credit.bus.tags[0].accounts[0].code, | ||||
|         self.assertEqual(len(editor.credit.bus.tags), 2) | ||||
|         self.assertEqual(editor.credit.bus.tags[0].name, "Train") | ||||
|         self.assertEqual(len(editor.credit.bus.tags[0].accounts), 2) | ||||
|         self.assertEqual(editor.credit.bus.tags[0].accounts[0].code, | ||||
|                          Accounts.PREPAID) | ||||
|         self.assertEqual(helper.credit.bus.tags[0].accounts[1].code, | ||||
|         self.assertEqual(editor.credit.bus.tags[0].accounts[1].code, | ||||
|                          Accounts.PAYABLE) | ||||
|         self.assertEqual(helper.credit.bus.tags[1].name, "Bus") | ||||
|         self.assertEqual(len(helper.credit.bus.tags[1].accounts), 1) | ||||
|         self.assertEqual(helper.credit.bus.tags[1].accounts[0].code, | ||||
|         self.assertEqual(editor.credit.bus.tags[1].name, "Bus") | ||||
|         self.assertEqual(len(editor.credit.bus.tags[1].accounts), 1) | ||||
|         self.assertEqual(editor.credit.bus.tags[1].accounts[0].code, | ||||
|                          Accounts.PREPAID) | ||||
| 
 | ||||
| 
 | ||||
		Reference in New Issue
	
	Block a user