No notifications are sent for appearing in a journal, but profile popovers etc. all work like mentions anywhere else in a topic.
297 lines
9.3 KiB
Plaintext
297 lines
9.3 KiB
Plaintext
import Component from "@glimmer/component";
|
|
import { tracked } from "@glimmer/tracking";
|
|
import { fn } from "@ember/helper";
|
|
import { action } from "@ember/object";
|
|
import { ajax } from "discourse/lib/ajax";
|
|
import { and, eq, isEmpty } from "discourse/truth-helpers";
|
|
import DButton from "discourse/ui-kit/d-button";
|
|
import DConditionalLoadingSpinner from "discourse/ui-kit/d-conditional-loading-spinner";
|
|
import DDatePicker from "discourse/ui-kit/d-date-picker";
|
|
import { i18n } from "discourse-i18n";
|
|
import { amountText } from "../lib/hledger-report";
|
|
import HledgerAccountCell from "./hledger-account-cell";
|
|
import HledgerAccountPath from "./hledger-account-path";
|
|
|
|
const REPORT_IDS = [
|
|
"accounts",
|
|
"balance_sheet",
|
|
"income_statement",
|
|
"equity",
|
|
"transactions",
|
|
];
|
|
|
|
export default class HledgerDashboard extends Component {
|
|
@tracked selectedReport = "accounts";
|
|
@tracked report = null;
|
|
@tracked loading = false;
|
|
@tracked error = null;
|
|
@tracked beginDate = null;
|
|
@tracked endDate = null;
|
|
|
|
constructor() {
|
|
super(...arguments);
|
|
this.loadReport();
|
|
}
|
|
|
|
get reports() {
|
|
return REPORT_IDS.map((id) => ({
|
|
id,
|
|
label: `hledger.reports.${id}`,
|
|
icon: {
|
|
accounts: "list",
|
|
balance_sheet: "scale-balanced",
|
|
income_statement: "chart-line",
|
|
equity: "users",
|
|
transactions: "receipt",
|
|
}[id],
|
|
}));
|
|
}
|
|
|
|
get topicId() {
|
|
return this.args.data?.post?.topic_id;
|
|
}
|
|
|
|
get isEquity() {
|
|
return this.selectedReport === "equity";
|
|
}
|
|
|
|
get isTransactions() {
|
|
return this.selectedReport === "transactions";
|
|
}
|
|
|
|
get labels() {
|
|
return {
|
|
total: i18n("hledger.total"),
|
|
net: i18n("hledger.net"),
|
|
noData: i18n("hledger.no_data"),
|
|
holder: i18n("hledger.equity.holder"),
|
|
amount: i18n("hledger.equity.amount"),
|
|
share: i18n("hledger.equity.share"),
|
|
note: i18n("hledger.equity.note"),
|
|
beginDate: i18n("hledger.filters.begin"),
|
|
endDate: i18n("hledger.filters.end"),
|
|
};
|
|
}
|
|
|
|
@action
|
|
select(reportId) {
|
|
if (this.selectedReport === reportId) {
|
|
return;
|
|
}
|
|
|
|
this.selectedReport = reportId;
|
|
this.loadReport();
|
|
}
|
|
|
|
@action
|
|
setBeginDate(value) {
|
|
this.beginDate = value;
|
|
this.loadReport();
|
|
}
|
|
|
|
@action
|
|
setEndDate(value) {
|
|
this.endDate = value;
|
|
this.loadReport();
|
|
}
|
|
|
|
@action
|
|
async loadReport() {
|
|
const topicId = this.topicId;
|
|
|
|
if (!topicId) {
|
|
return;
|
|
}
|
|
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
const data = {};
|
|
if (this.beginDate) {
|
|
data.begin = this.beginDate;
|
|
}
|
|
if (this.endDate) {
|
|
data.end = this.endDate;
|
|
}
|
|
|
|
try {
|
|
this.report = await ajax(
|
|
`/hledger/topics/${topicId}/reports/${this.selectedReport}`,
|
|
{ data }
|
|
);
|
|
} catch (e) {
|
|
this.report = null;
|
|
this.error =
|
|
e?.jqXHR?.responseJSON?.errors?.[0] || i18n("hledger.errors.generic");
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
}
|
|
|
|
<template>
|
|
<div class="hledger-dashboard__inner">
|
|
<div class="hledger-dashboard__toolbar">
|
|
{{#each this.reports as |report|}}
|
|
<DButton
|
|
class={{if (eq this.selectedReport report.id) "is-active"}}
|
|
@label={{report.label}}
|
|
@icon={{report.icon}}
|
|
@action={{fn this.select report.id}}
|
|
@disabled={{this.loading}}
|
|
/>
|
|
{{/each}}
|
|
</div>
|
|
|
|
<div class="hledger-dashboard__filters">
|
|
<DDatePicker
|
|
@value={{this.beginDate}}
|
|
@onSelect={{this.setBeginDate}}
|
|
@placeholder={{this.labels.beginDate}}
|
|
/>
|
|
<DDatePicker
|
|
@value={{this.endDate}}
|
|
@onSelect={{this.setEndDate}}
|
|
@placeholder={{this.labels.endDate}}
|
|
/>
|
|
</div>
|
|
|
|
<DConditionalLoadingSpinner @condition={{this.loading}}>
|
|
{{#if this.error}}
|
|
<div
|
|
class="hledger-dashboard__error alert alert-error"
|
|
>{{this.error}}</div>
|
|
{{else if this.report}}
|
|
{{#if this.isEquity}}
|
|
{{#each this.report.groups as |group|}}
|
|
<div class="hledger-dashboard__section">
|
|
<h3
|
|
class="hledger-dashboard__section-title"
|
|
>{{group.commodity}}</h3>
|
|
<table class="hledger-dashboard__table">
|
|
<thead>
|
|
<tr>
|
|
<th>{{this.labels.holder}}</th>
|
|
<th
|
|
class="hledger-dashboard__amount"
|
|
>{{this.labels.amount}}</th>
|
|
<th
|
|
class="hledger-dashboard__amount"
|
|
>{{this.labels.share}}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{#each group.rows as |row|}}
|
|
<tr>
|
|
<HledgerAccountCell @row={{row}} />
|
|
<td class="hledger-dashboard__amount">{{amountText
|
|
row.amounts
|
|
}}</td>
|
|
<td
|
|
class="hledger-dashboard__amount"
|
|
>{{row.percentage}}%</td>
|
|
</tr>
|
|
{{/each}}
|
|
<tr class="hledger-dashboard__total">
|
|
<td>{{this.labels.total}}</td>
|
|
<td
|
|
class="hledger-dashboard__amount"
|
|
>{{group.total.display}}</td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{/each}}
|
|
<p class="hledger-dashboard__note">{{this.labels.note}}</p>
|
|
{{else if this.isTransactions}}
|
|
{{#if this.report.transactions.length}}
|
|
{{#each this.report.transactions as |transaction|}}
|
|
<div class="hledger-dashboard__transaction">
|
|
<div class="hledger-dashboard__transaction-header">
|
|
<span
|
|
class="hledger-dashboard__transaction-date"
|
|
>{{transaction.date}}</span>
|
|
<span
|
|
class="hledger-dashboard__transaction-description"
|
|
>{{transaction.description}}</span>
|
|
</div>
|
|
<table class="hledger-dashboard__table">
|
|
<tbody>
|
|
{{#each transaction.postings as |posting|}}
|
|
<tr>
|
|
<td
|
|
class="hledger-dashboard__account"
|
|
title={{posting.account}}
|
|
>
|
|
{{#if posting.account_segments}}
|
|
<HledgerAccountPath
|
|
@segments={{posting.account_segments}}
|
|
/>
|
|
{{else}}
|
|
{{posting.account}}
|
|
{{/if}}
|
|
</td>
|
|
<td class="hledger-dashboard__amount">{{amountText
|
|
posting.amounts
|
|
}}</td>
|
|
</tr>
|
|
{{/each}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{/each}}
|
|
{{else}}
|
|
<p class="hledger-dashboard__empty">{{this.labels.noData}}</p>
|
|
{{/if}}
|
|
{{else}}
|
|
{{#each this.report.sections as |section|}}
|
|
<div class="hledger-dashboard__section">
|
|
{{#if section.title}}
|
|
<h3
|
|
class="hledger-dashboard__section-title"
|
|
>{{section.title}}</h3>
|
|
{{/if}}
|
|
{{#if (and section.title (isEmpty section.rows))}}
|
|
<p class="hledger-dashboard__empty">{{this.labels.noData}}</p>
|
|
{{else}}
|
|
<table class="hledger-dashboard__table">
|
|
<tbody>
|
|
{{#each section.rows as |row|}}
|
|
<tr>
|
|
<HledgerAccountCell
|
|
@row={{row}}
|
|
@boldRoot={{row.root}}
|
|
/>
|
|
<td class="hledger-dashboard__amount">{{amountText
|
|
row.amounts
|
|
}}</td>
|
|
</tr>
|
|
{{/each}}
|
|
{{#if section.total}}
|
|
<tr class="hledger-dashboard__total">
|
|
<td>{{this.labels.total}}</td>
|
|
<td class="hledger-dashboard__amount">{{amountText
|
|
section.total
|
|
}}</td>
|
|
</tr>
|
|
{{/if}}
|
|
</tbody>
|
|
</table>
|
|
{{/if}}
|
|
</div>
|
|
{{/each}}
|
|
{{#if this.report.net}}
|
|
<div class="hledger-dashboard__net">
|
|
<span>{{this.labels.net}}</span>
|
|
<span class="hledger-dashboard__amount">{{amountText
|
|
this.report.net
|
|
}}</span>
|
|
</div>
|
|
{{/if}}
|
|
{{/if}}
|
|
{{/if}}
|
|
</DConditionalLoadingSpinner>
|
|
</div>
|
|
</template>
|
|
}
|